@bolloon/bolloon-agent 0.1.1 → 0.1.3

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 (200) hide show
  1. package/bin/bolloon-cli.cjs +165 -0
  2. package/bin/bolloon-daemon.sh +207 -0
  3. package/bin/bolloon.cmd +11 -0
  4. package/dist/agents/constraint-layer.js +10 -15
  5. package/dist/agents/pi-sdk.js +433 -106
  6. package/dist/agents/protocol.js +82 -1
  7. package/dist/agents/subagent-manager.js +2 -2
  8. package/dist/agents/workflow-engine.js +15 -20
  9. package/dist/agents/workflow-pivot-loop.js +541 -0
  10. package/dist/bollharness/src/index.js +5 -0
  11. package/dist/bollharness/src/scripts/checks/check_adr_plan_numbering.js +6 -0
  12. package/dist/bollharness/src/scripts/checks/check_api_types.js +45 -0
  13. package/dist/bollharness/src/scripts/checks/check_artifact_link.js +146 -0
  14. package/dist/bollharness/src/scripts/checks/check_bridge_deps.js +6 -0
  15. package/dist/bollharness/src/scripts/checks/check_bugfix_binding.js +6 -0
  16. package/dist/bollharness/src/scripts/checks/check_bugfix_binding_ci.js +6 -0
  17. package/dist/bollharness/src/scripts/checks/check_doc_file_references.js +6 -0
  18. package/dist/bollharness/src/scripts/checks/check_doc_freshness.js +135 -0
  19. package/dist/bollharness/src/scripts/checks/check_doc_links.js +31 -0
  20. package/dist/bollharness/src/scripts/checks/check_file_existence_claims.js +6 -0
  21. package/dist/bollharness/src/scripts/checks/check_fragment_integrity.js +34 -0
  22. package/dist/bollharness/src/scripts/checks/check_hook_installed.js +63 -0
  23. package/dist/bollharness/src/scripts/checks/check_issue_closure.js +41 -0
  24. package/dist/bollharness/src/scripts/checks/check_mcp_parity.js +6 -0
  25. package/dist/bollharness/src/scripts/checks/check_security.js +48 -0
  26. package/dist/bollharness/src/scripts/checks/check_skill_parity.js +6 -0
  27. package/dist/bollharness/src/scripts/checks/check_versions.js +6 -0
  28. package/dist/bollharness/src/scripts/checks/finding.js +13 -0
  29. package/dist/bollharness/src/scripts/checks/next_decision_number.js +20 -0
  30. package/dist/bollharness/src/scripts/checks/regenerate_magic_docs.js +6 -0
  31. package/dist/bollharness/src/scripts/ci/detect_rebaseline_triggers.js +8 -0
  32. package/dist/bollharness/src/scripts/ci/scan_subprocess_cfg.js +8 -0
  33. package/dist/bollharness/src/scripts/ci/scan_verify_artifacts.js +8 -0
  34. package/dist/bollharness/src/scripts/ci/scan_yaml_schema.js +8 -0
  35. package/dist/bollharness/src/scripts/context_router.js +67 -0
  36. package/dist/bollharness/src/scripts/deploy-guard.js +157 -0
  37. package/dist/bollharness/src/scripts/guard-feedback.js +192 -0
  38. package/dist/bollharness/src/scripts/guard_router.js +158 -0
  39. package/dist/bollharness/src/scripts/hooks/_hook_output.js +6 -0
  40. package/dist/bollharness/src/scripts/hooks/auto-python3.js +6 -0
  41. package/dist/bollharness/src/scripts/hooks/deploy-progress-on-session-end.js +6 -0
  42. package/dist/bollharness/src/scripts/hooks/failure-analyzer.js +6 -0
  43. package/dist/bollharness/src/scripts/hooks/gate-judgment-inject.js +92 -0
  44. package/dist/bollharness/src/scripts/hooks/gate-transition-judgment.js +63 -0
  45. package/dist/bollharness/src/scripts/hooks/inbox-ack.js +6 -0
  46. package/dist/bollharness/src/scripts/hooks/inbox-inject-on-start.js +6 -0
  47. package/dist/bollharness/src/scripts/hooks/inbox-validate.js +6 -0
  48. package/dist/bollharness/src/scripts/hooks/inbox-write-ledger.js +6 -0
  49. package/dist/bollharness/src/scripts/hooks/initializer-agent.js +6 -0
  50. package/dist/bollharness/src/scripts/hooks/loop-detection.js +73 -0
  51. package/dist/bollharness/src/scripts/hooks/owner-guard.js +6 -0
  52. package/dist/bollharness/src/scripts/hooks/precompact.js +6 -0
  53. package/dist/bollharness/src/scripts/hooks/review-agent-gatekeeper.js +6 -0
  54. package/dist/bollharness/src/scripts/hooks/risk-tracker.js +108 -0
  55. package/dist/bollharness/src/scripts/hooks/sanitize-on-read.js +6 -0
  56. package/dist/bollharness/src/scripts/hooks/session-reflection.js +7 -0
  57. package/dist/bollharness/src/scripts/hooks/session-start-magic-docs.js +7 -0
  58. package/dist/bollharness/src/scripts/hooks/session-start-reset-risk.js +7 -0
  59. package/dist/bollharness/src/scripts/hooks/session-start-toolkit-reminder.js +7 -0
  60. package/dist/bollharness/src/scripts/hooks/stop-evaluator.js +157 -0
  61. package/dist/bollharness/src/scripts/hooks/tool-call-counter.js +6 -0
  62. package/dist/bollharness/src/scripts/hooks/trace-analyzer.js +10 -0
  63. package/dist/bollharness/src/scripts/install/install-trust-token.js +7 -0
  64. package/dist/bollharness/src/scripts/install/multi_project_registry.js +9 -0
  65. package/dist/bollharness/src/scripts/install/phase2_auto.js +21 -0
  66. package/dist/bollharness/src/scripts/install/pre_commit_installer.js +6 -0
  67. package/dist/bollharness/src/scripts/install/tier_selector.js +7 -0
  68. package/dist/bollharness/src/scripts/install/transcript_miner.js +7 -0
  69. package/dist/bollharness/src/scripts/lib/claim_patterns.js +10 -0
  70. package/dist/bollharness/src/scripts/lib/sanitize_patterns.js +12 -0
  71. package/dist/bollharness/src/scripts/sanitize.js +6 -0
  72. package/dist/bollharness-integration/channel-judgment-engine.js +530 -0
  73. package/dist/bollharness-integration/context-chain-router.js +383 -0
  74. package/dist/bollharness-integration/context-router-judgment.js +13 -21
  75. package/dist/bollharness-integration/context-router.js +22 -64
  76. package/dist/bollharness-integration/gate-state-machine.js +14 -19
  77. package/dist/bollharness-integration/gate-transition-hooks.js +16 -61
  78. package/dist/bollharness-integration/guard-checker.js +21 -68
  79. package/dist/bollharness-integration/index.js +14 -124
  80. package/dist/bollharness-integration/integration.js +13 -20
  81. package/dist/bollharness-integration/llm-judgment-engine.js +569 -0
  82. package/dist/bollharness-integration/skill-adapter.js +18 -64
  83. package/dist/cli-entry.js +261 -0
  84. package/dist/constraint-runtime/src/commands.js +17 -7
  85. package/dist/constraint-runtime/src/constraint/budget.js +1 -6
  86. package/dist/constraint-runtime/src/constraint/permission.js +1 -6
  87. package/dist/constraint-runtime/src/models.js +1 -3
  88. package/dist/constraint-runtime/src/tools.js +17 -7
  89. package/dist/constraints/index.js +1 -7
  90. package/dist/documents/reader.js +8 -49
  91. package/dist/heartbeat/DaemonManager.js +242 -0
  92. package/dist/heartbeat/HealthMonitor.js +285 -0
  93. package/dist/heartbeat/StartupVerifier.js +205 -0
  94. package/dist/heartbeat/Watchdog.js +168 -0
  95. package/dist/heartbeat/index.js +84 -0
  96. package/dist/heartbeat/types.js +5 -0
  97. package/dist/index.js +381 -28
  98. package/dist/llm/config-store.js +31 -57
  99. package/dist/llm/llm-judgment-client.js +389 -0
  100. package/dist/llm/pi-ai.js +9 -52
  101. package/dist/network/agent-network.js +46 -90
  102. package/dist/network/hybrid-messenger.js +125 -0
  103. package/dist/network/iroh-bootstrap.js +38 -0
  104. package/dist/network/iroh-discovery.js +145 -0
  105. package/dist/network/iroh-integration.js +9 -16
  106. package/dist/network/iroh-transport.js +10 -48
  107. package/dist/network/p2p.js +23 -62
  108. package/dist/network/storage/adapters/json-adapter.js +4 -42
  109. package/dist/network/storage/index.js +147 -0
  110. package/dist/network/storage/types.js +14 -0
  111. package/dist/pi-ecosystem/index.js +233 -0
  112. package/dist/pi-ecosystem-colony/index.js +29 -90
  113. package/dist/pi-ecosystem-goals/index.js +20 -74
  114. package/dist/pi-ecosystem-judgment/decision.js +29 -47
  115. package/dist/pi-ecosystem-judgment/distillation.js +16 -29
  116. package/dist/pi-ecosystem-judgment/human-value-store.js +13 -60
  117. package/dist/pi-ecosystem-judgment/index.js +21 -74
  118. package/dist/pi-ecosystem-judgment/value-injection.js +26 -72
  119. package/dist/pi-ecosystem-mcp/index.js +24 -78
  120. package/dist/pi-ecosystem-subagents/index.js +20 -69
  121. package/dist/social/ant-colony/AdaptiveHeartbeat.js +3 -8
  122. package/dist/social/ant-colony/PheromoneEngine.js +11 -49
  123. package/dist/social/ant-colony/index.js +6 -0
  124. package/dist/social/ant-colony/types.js +4 -8
  125. package/dist/social/channels/ChannelManager.js +8 -46
  126. package/dist/social/channels/DiapChannelBridge.js +9 -47
  127. package/dist/social/channels/InterestMatcher.js +2 -7
  128. package/dist/social/channels/channel-agent-session.js +309 -0
  129. package/dist/social/channels/channel-heartbeat-agent.js +494 -0
  130. package/dist/social/channels/diap-doc-parser.js +204 -0
  131. package/dist/social/channels/harness-workflow-integrator.js +446 -0
  132. package/dist/social/channels/index.js +9 -0
  133. package/dist/social/channels/types.js +3 -7
  134. package/dist/social/global-shared-context.js +6 -47
  135. package/dist/social/heartbeat.js +29 -72
  136. package/dist/social/persona/enhanced-persona.js +299 -0
  137. package/dist/web/client.js +302 -136
  138. package/dist/web/components/p2p/index.js +159 -9
  139. package/dist/web/components/p2p/p2p-connection.js +136 -0
  140. package/dist/web/components/p2p/p2p-manager.js +24 -0
  141. package/dist/web/components/p2p/p2p-store-memory.js +1 -1
  142. package/dist/web/components/p2p/types.js +7 -0
  143. package/dist/web/index.html +5 -0
  144. package/dist/web/style.css +118 -0
  145. package/package.json +12 -6
  146. package/scripts/build-cli.js +206 -0
  147. package/scripts/postinstall.js +153 -0
  148. package/src/agents/pi-sdk.ts +347 -28
  149. package/src/agents/protocol.ts +95 -1
  150. package/src/agents/workflow-pivot-loop.ts +674 -0
  151. package/src/bollharness/CLAUDE.md +73 -0
  152. package/src/bollharness/README.md +143 -0
  153. package/src/bollharness/README.zh-CN.md +131 -0
  154. package/src/bollharness/reference/boll-reference/scripts/hooks/stop-evaluator.md +57 -0
  155. package/src/bollharness/scripts/context-fragments/artifact-linkage.md +14 -0
  156. package/src/bollharness/scripts/context-fragments/auth-consumers.md +17 -0
  157. package/src/bollharness/scripts/context-fragments/bridge-constitution.md +13 -0
  158. package/src/bollharness/scripts/context-fragments/catalyst-distributed.md +18 -0
  159. package/src/bollharness/scripts/context-fragments/closure-checklist.md +13 -0
  160. package/src/bollharness/scripts/context-fragments/contract-consumers.md +15 -0
  161. package/src/bollharness/scripts/context-fragments/db-shared-structures.md +15 -0
  162. package/src/bollharness/scripts/context-fragments/fixed-three-layers.md +19 -0
  163. package/src/bollharness/scripts/context-fragments/general-dev-principles.md +11 -0
  164. package/src/bollharness/scripts/context-fragments/issue-first.md +8 -0
  165. package/src/bollharness/scripts/context-fragments/mcp-parity.md +16 -0
  166. package/src/bollharness/scripts/context-fragments/pi-agent-operations.md +108 -0
  167. package/src/bollharness/scripts/context-fragments/protocol-consumers.md +15 -0
  168. package/src/bollharness/scripts/context-fragments/run-events-consumers.md +15 -0
  169. package/src/bollharness/scripts/context-fragments/scene-fidelity.md +13 -0
  170. package/src/bollharness/scripts/context-fragments/truth-source-hierarchy.md +15 -0
  171. package/src/bollharness/scripts/context-fragments/two-language.md +15 -0
  172. package/src/bollharness/scripts/context-fragments/version-sources.md +14 -0
  173. package/src/bollharness/scripts/hooks/stop-evaluator.md +83 -0
  174. package/src/bollharness/templates/scaffold/CLAUDE.md +89 -0
  175. package/src/cli-entry.ts +304 -0
  176. package/src/heartbeat/DaemonManager.ts +283 -0
  177. package/src/heartbeat/HealthMonitor.ts +316 -0
  178. package/src/heartbeat/StartupVerifier.ts +223 -0
  179. package/src/heartbeat/Watchdog.ts +198 -0
  180. package/src/heartbeat/index.ts +108 -0
  181. package/src/heartbeat/types.ts +82 -0
  182. package/src/llm/config-store.ts +23 -5
  183. package/src/network/iroh-transport.ts +3 -3
  184. package/src/web/client.js +302 -136
  185. package/src/web/components/p2p/P2PModal.tsx +91 -3
  186. package/src/web/components/p2p/index.ts +171 -9
  187. package/src/web/components/p2p/p2p-connection.ts +153 -1
  188. package/src/web/components/p2p/p2p-manager.ts +39 -1
  189. package/src/web/components/p2p/p2p-store-memory.ts +1 -1
  190. package/src/web/components/p2p/p2p-tools.ts +315 -0
  191. package/src/web/components/p2p/types.ts +58 -0
  192. package/src/web/design.md +99 -0
  193. package/src/web/index.html +5 -0
  194. package/src/web/server.ts +353 -36
  195. package/src/web/style.css +118 -0
  196. package/tsconfig.cli.json +16 -0
  197. package/tsconfig.electron.json +1 -1
  198. package/tsconfig.json +1 -2
  199. package/dist/web/server.js +0 -1647
  200. package/dist/web/server.js.map +0 -1
@@ -0,0 +1,383 @@
1
+ /**
2
+ * Context Chain Router - Session summary chain injection
3
+ *
4
+ * Integrates with existing ContextRouter and Judgment systems.
5
+ *
6
+ * Architecture:
7
+ * - Session end → extract summary by work_type → store in .boll/state/context-chains/
8
+ * - Session start (Gate 0/3) → lookup related chains → inject summaries
9
+ * - Work type: code_change | review | design | question | planning | debugging
10
+ *
11
+ * Integration points:
12
+ * - Uses existing context-router-judgment.ts pattern (extends, not replaces)
13
+ * - Gate injection via gate-judgment-inject.ts
14
+ * - Storage in .boll/state/context-chains/
15
+ */
16
+ import * as fs from 'fs';
17
+ import * as path from 'path';
18
+ export const CONTEXT_CHAINS_DIR = path.join('.boll', 'state', 'context-chains');
19
+ /**
20
+ * Ensure context-chains directory exists
21
+ */
22
+ function ensureDir() {
23
+ if (!fs.existsSync(CONTEXT_CHAINS_DIR)) {
24
+ fs.mkdirSync(CONTEXT_CHAINS_DIR, { recursive: true });
25
+ }
26
+ }
27
+ /**
28
+ * Get current month directory path
29
+ */
30
+ function getMonthDir() {
31
+ const now = new Date();
32
+ const year = now.getFullYear();
33
+ const month = String(now.getMonth() + 1).padStart(2, '0');
34
+ return path.join(CONTEXT_CHAINS_DIR, `${year}-${month}`);
35
+ }
36
+ /**
37
+ * Generate session ID
38
+ */
39
+ function generateSessionId() {
40
+ const now = new Date();
41
+ const year = now.getFullYear();
42
+ const month = String(now.getMonth() + 1).padStart(2, '0');
43
+ const day = String(now.getDate()).padStart(2, '0');
44
+ const seq = getTodaySequence() + 1;
45
+ return `${year}${month}${day}-${String(seq).padStart(3, '0')}`;
46
+ }
47
+ /**
48
+ * Get today's sequence number
49
+ */
50
+ function getTodaySequence() {
51
+ const dir = getMonthDir();
52
+ if (!fs.existsSync(dir))
53
+ return 0;
54
+ const todayPrefix = new Date().toISOString().slice(0, 10).replace(/-/g, '');
55
+ const files = fs.readdirSync(dir)
56
+ .filter(f => f.startsWith(todayPrefix) && f.endsWith('.yaml'));
57
+ return files.length;
58
+ }
59
+ /**
60
+ * Save a context chain summary
61
+ */
62
+ export function saveContextChain(summary) {
63
+ ensureDir();
64
+ const monthDir = getMonthDir();
65
+ if (!fs.existsSync(monthDir)) {
66
+ fs.mkdirSync(monthDir, { recursive: true });
67
+ }
68
+ const filename = `${summary.session_id}-${summary.work_type}-${getTodaySequence() + 1}.yaml`;
69
+ const filepath = path.join(monthDir, filename);
70
+ const yaml = contextChainToYaml(summary);
71
+ fs.writeFileSync(filepath, yaml, 'utf-8');
72
+ return filepath;
73
+ }
74
+ /**
75
+ * Convert context chain to YAML string
76
+ */
77
+ function contextChainToYaml(summary) {
78
+ const lines = [
79
+ `session_id: "${summary.session_id}"`,
80
+ `work_type: ${summary.work_type}`,
81
+ `created_at: "${summary.created_at}"`,
82
+ `gate_at_session: ${summary.gate_at_session}`,
83
+ '',
84
+ '关联上下文:',
85
+ ];
86
+ for (const ref of summary['关联上下文']) {
87
+ lines.push(` - session_id: "${ref.session_id}"`);
88
+ lines.push(` reason: "${ref.reason}"`);
89
+ lines.push(` relevance: ${ref.relevance}`);
90
+ }
91
+ lines.push('');
92
+ lines.push('核心摘要:');
93
+ const core = summary['核心摘要'];
94
+ for (const [key, value] of Object.entries(core)) {
95
+ if (Array.isArray(value)) {
96
+ lines.push(` ${key}:`);
97
+ for (const item of value) {
98
+ if (typeof item === 'object') {
99
+ for (const [k, v] of Object.entries(item)) {
100
+ lines.push(` - ${k}: ${JSON.stringify(v)}`);
101
+ }
102
+ }
103
+ else {
104
+ lines.push(` - ${JSON.stringify(item)}`);
105
+ }
106
+ }
107
+ }
108
+ else if (typeof value === 'object' && value !== null) {
109
+ lines.push(` ${key}:`);
110
+ for (const [k, v] of Object.entries(value)) {
111
+ lines.push(` ${k}: ${JSON.stringify(v)}`);
112
+ }
113
+ }
114
+ else {
115
+ lines.push(` ${key}: ${JSON.stringify(value)}`);
116
+ }
117
+ }
118
+ if (summary['决策缺口'] && summary['决策缺口'].length > 0) {
119
+ lines.push('');
120
+ lines.push('决策缺口:');
121
+ for (const gap of summary['决策缺口']) {
122
+ lines.push(` - 描述: "${gap.描述}"`);
123
+ lines.push(` 影响: "${gap.影响}"`);
124
+ lines.push(` 需要什么才能关闭: "${gap.需要什么才能关闭}"`);
125
+ }
126
+ }
127
+ if (summary['风险点'] && summary['风险点'].length > 0) {
128
+ lines.push('');
129
+ lines.push('风险点:');
130
+ for (const risk of summary['风险点']) {
131
+ lines.push(` - 描述: "${risk.描述}"`);
132
+ lines.push(` 概率: ${risk.概率}`);
133
+ lines.push(` 缓解措施: "${risk.缓解措施}"`);
134
+ }
135
+ }
136
+ if (summary['遗迹'] && summary['遗迹'].length > 0) {
137
+ lines.push('');
138
+ lines.push('遗迹:');
139
+ for (const relic of summary['遗迹']) {
140
+ lines.push(` - "${relic}"`);
141
+ }
142
+ }
143
+ return lines.join('\n');
144
+ }
145
+ /**
146
+ * Load a single context chain by session_id
147
+ */
148
+ export function loadContextChain(sessionId) {
149
+ const pattern = new RegExp(`^${sessionId.replace(/-/g, '.*')}-.*\\.yaml$`);
150
+ const dirs = fs.existsSync(CONTEXT_CHAINS_DIR)
151
+ ? fs.readdirSync(CONTEXT_CHAINS_DIR)
152
+ : [];
153
+ for (const dir of dirs) {
154
+ const dirPath = path.join(CONTEXT_CHAINS_DIR, dir);
155
+ if (!fs.statSync(dirPath).isDirectory())
156
+ continue;
157
+ const files = fs.readdirSync(dirPath).filter(f => pattern.test(f));
158
+ if (files.length > 0) {
159
+ const content = fs.readFileSync(path.join(dirPath, files[0]), 'utf-8');
160
+ return parseContextChainYaml(content);
161
+ }
162
+ }
163
+ return null;
164
+ }
165
+ /**
166
+ * Parse YAML content to ContextChainSummary
167
+ */
168
+ function parseContextChainYaml(content) {
169
+ const result = {};
170
+ const lines = content.split('\n');
171
+ let currentKey = '';
172
+ let currentArray = [];
173
+ let inArray = false;
174
+ for (const line of lines) {
175
+ if (line.includes(':') && !line.startsWith(' ')) {
176
+ const [key, ...valueParts] = line.split(':');
177
+ const value = valueParts.join(':').trim();
178
+ if (inArray && currentKey) {
179
+ result[currentKey] = currentArray;
180
+ currentArray = [];
181
+ inArray = false;
182
+ }
183
+ currentKey = key.trim();
184
+ if (value) {
185
+ result[currentKey] = value.replace(/^["']|["']$/g, '');
186
+ }
187
+ }
188
+ else if (line.startsWith(' - ')) {
189
+ inArray = true;
190
+ currentArray.push(line.replace(/^ - /, '').replace(/^["']|["']$/g, ''));
191
+ }
192
+ }
193
+ if (inArray && currentKey) {
194
+ result[currentKey] = currentArray;
195
+ }
196
+ return result;
197
+ }
198
+ /**
199
+ * Find related context chains by work type and relevance
200
+ */
201
+ export function findRelatedChains(options = {}) {
202
+ const { workType, minRelevance = 0.5, maxTokens = 2000, gate, } = options;
203
+ if (!fs.existsSync(CONTEXT_CHAINS_DIR)) {
204
+ return [];
205
+ }
206
+ const chains = [];
207
+ const dirs = fs.readdirSync(CONTEXT_CHAINS_DIR);
208
+ for (const dir of dirs) {
209
+ const dirPath = path.join(CONTEXT_CHAINS_DIR, dir);
210
+ if (!fs.statSync(dirPath).isDirectory())
211
+ continue;
212
+ const files = fs.readdirSync(dirPath).filter(f => f.endsWith('.yaml'));
213
+ for (const file of files) {
214
+ const content = fs.readFileSync(path.join(dirPath, file), 'utf-8');
215
+ const chain = parseContextChainYaml(content);
216
+ if (workType && chain.work_type !== workType)
217
+ continue;
218
+ if (gate !== undefined && chain.gate_at_session !== gate)
219
+ continue;
220
+ chains.push(chain);
221
+ }
222
+ }
223
+ // Sort by relevance and recency
224
+ chains.sort((a, b) => {
225
+ const aRecency = new Date(a.created_at).getTime();
226
+ const bRecency = new Date(b.created_at).getTime();
227
+ return bRecency - aRecency;
228
+ });
229
+ // Apply token budget
230
+ let totalTokens = 0;
231
+ const selected = [];
232
+ for (const chain of chains) {
233
+ const estimatedTokens = estimateTokens(chain);
234
+ if (totalTokens + estimatedTokens > maxTokens)
235
+ break;
236
+ selected.push(chain);
237
+ totalTokens += estimatedTokens;
238
+ }
239
+ return selected;
240
+ }
241
+ /**
242
+ * Estimate token count for a chain
243
+ */
244
+ function estimateTokens(chain) {
245
+ const yaml = contextChainToYaml(chain);
246
+ return Math.ceil(yaml.length / 4);
247
+ }
248
+ /**
249
+ * Generate injection for Gate 0/3
250
+ */
251
+ export async function generateContextChainInjection(gate, workType) {
252
+ const chains = findRelatedChains({
253
+ workType,
254
+ gate: gate === 0 ? undefined : gate,
255
+ maxTokens: 2000,
256
+ });
257
+ if (chains.length === 0) {
258
+ return '';
259
+ }
260
+ const header = gate === 0
261
+ ? '# Context Chains — Recent Session Summaries'
262
+ : `# Context Chains — Gate ${gate} Related Sessions`;
263
+ const lines = [
264
+ header,
265
+ `# Injected at session start — chains from related prior sessions`,
266
+ `# Total chains: ${chains.length} | Token budget: ~2000`,
267
+ '',
268
+ 'context_chains:',
269
+ ];
270
+ for (const chain of chains) {
271
+ lines.push(` - session_id: "${chain.session_id}"`);
272
+ lines.push(` work_type: ${chain.work_type}`);
273
+ lines.push(` created_at: "${chain.created_at}"`);
274
+ lines.push(` gate_at_session: ${chain.gate_at_session}`);
275
+ if (chain['关联上下文'].length > 0) {
276
+ lines.push(` 关联上下文:`);
277
+ for (const ref of chain['关联上下文']) {
278
+ lines.push(` - session_id: "${ref.session_id}"`);
279
+ lines.push(` relevance: ${ref.relevance}`);
280
+ }
281
+ }
282
+ lines.push(` 核心摘要:`);
283
+ const core = chain['核心摘要'];
284
+ for (const [key, value] of Object.entries(core)) {
285
+ if (Array.isArray(value)) {
286
+ lines.push(` ${key}:`);
287
+ for (const item of value.slice(0, 3)) {
288
+ if (typeof item === 'object') {
289
+ lines.push(` - ${JSON.stringify(item).slice(0, 100)}`);
290
+ }
291
+ else {
292
+ lines.push(` - ${JSON.stringify(item).slice(0, 100)}`);
293
+ }
294
+ }
295
+ if (value.length > 3) {
296
+ lines.push(` ... (${value.length - 3} more)`);
297
+ }
298
+ }
299
+ else if (typeof value === 'string' && value.length > 100) {
300
+ lines.push(` ${key}: "${value.slice(0, 100)}..."`);
301
+ }
302
+ else {
303
+ lines.push(` ${key}: ${JSON.stringify(value)}`);
304
+ }
305
+ }
306
+ lines.push('');
307
+ }
308
+ return lines.join('\n');
309
+ }
310
+ /**
311
+ * Create a new context chain summary from conversation
312
+ */
313
+ export function createContextChain(params) {
314
+ const sessionId = generateSessionId();
315
+ const summary = {
316
+ session_id: sessionId,
317
+ work_type: params.workType,
318
+ created_at: new Date().toISOString(),
319
+ gate_at_session: params.gate,
320
+ '关联上下文': (params.relatedSessions || []).map(r => ({
321
+ session_id: r.sessionId,
322
+ reason: r.reason,
323
+ relevance: r.relevance,
324
+ })),
325
+ '核心摘要': extractCoreSummary(params.workType, params.conversationText),
326
+ '决策缺口': [],
327
+ '风险点': [],
328
+ '遗迹': [],
329
+ };
330
+ return summary;
331
+ }
332
+ /**
333
+ * Extract core summary based on work type
334
+ */
335
+ function extractCoreSummary(workType, text) {
336
+ switch (workType) {
337
+ case 'code_change':
338
+ return extractCodeChangeSummary(text);
339
+ case 'review':
340
+ return extractReviewSummary(text);
341
+ case 'design':
342
+ return extractDesignSummary(text);
343
+ case 'planning':
344
+ return extractPlanningSummary(text);
345
+ case 'debugging':
346
+ return extractDebuggingSummary(text);
347
+ case 'question':
348
+ return extractQuestionSummary(text);
349
+ default:
350
+ return { raw: text.slice(0, 500) };
351
+ }
352
+ }
353
+ function extractCodeChangeSummary(text) {
354
+ const files = [];
355
+ // Extract file paths from common patterns
356
+ const filePattern = /(?:modified|changed|added|deleted):\s+([^\s]+)/gi;
357
+ let match;
358
+ while ((match = filePattern.exec(text)) !== null) {
359
+ files.push({ path: match[1], change_type: 'modify', reason: '' });
360
+ }
361
+ return { files_changed: files, decisions: [], adr_linked: [] };
362
+ }
363
+ function extractReviewSummary(text) {
364
+ const hasBlock = text.toLowerCase().includes('block') || text.toLowerCase().includes('reject');
365
+ return {
366
+ verdict: hasBlock ? 'BLOCK' : 'PASS',
367
+ reviewed_artifact: '',
368
+ blocking_issues: [],
369
+ non_blocking_observations: [],
370
+ };
371
+ }
372
+ function extractDesignSummary(text) {
373
+ return { design_choices: [], constraints: [], consumers: [] };
374
+ }
375
+ function extractPlanningSummary(text) {
376
+ return { goals: [], dependencies: [], risks: [], decision_gaps: [] };
377
+ }
378
+ function extractDebuggingSummary(text) {
379
+ return { root_cause: '', symptoms_observed: [], fix_applied: [], files_touched: [] };
380
+ }
381
+ function extractQuestionSummary(text) {
382
+ return { question_type: 'unknown', answer_summary: '', source: '' };
383
+ }
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  /**
3
2
  * Judgment-Aware Context Router
4
3
  *
@@ -14,14 +13,8 @@
14
13
  * - Extends with judgment lookup based on fragment context
15
14
  * - Injects at Gate 0, Gate 3, and file-edit time
16
15
  */
17
- Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.getJudgmentsForFragment = getJudgmentsForFragment;
19
- exports.getJudgmentsForPath = getJudgmentsForPath;
20
- exports.getCoreJudgmentsForSession = getCoreJudgmentsForSession;
21
- exports.getJudgmentsForContextRequest = getJudgmentsForContextRequest;
22
- exports.generateJudgmentInjection = generateJudgmentInjection;
23
- const context_router_js_1 = require("./context-router.js");
24
- const index_js_1 = require("../pi-ecosystem-judgment/index.js");
16
+ import { match as contextMatch, } from './context-router.js';
17
+ import { getCombinedJudgments, getJudgmentsForContext, calculateConfidence, } from '../pi-ecosystem-judgment/index.js';
25
18
  const DEFAULT_OPTIONS = {
26
19
  minConfidence: 0.7,
27
20
  maxJudgments: 5,
@@ -31,8 +24,8 @@ const DEFAULT_OPTIONS = {
31
24
  /**
32
25
  * Get judgments associated with a fragment name
33
26
  */
34
- async function getJudgmentsForFragment(fragmentName) {
35
- const allJudgments = await (0, index_js_1.getCombinedJudgments)();
27
+ export async function getJudgmentsForFragment(fragmentName) {
28
+ const allJudgments = await getCombinedJudgments();
36
29
  // Map fragment to judgment context categories
37
30
  const fragmentContextMap = {
38
31
  'truth-source-hierarchy': ['truth-source', 'code', 'architecture', 'hierarchy', 'priority'],
@@ -62,10 +55,10 @@ async function getJudgmentsForFragment(fragmentName) {
62
55
  /**
63
56
  * Get high-confidence judgments for a file path
64
57
  */
65
- async function getJudgmentsForPath(filePath, options = {}) {
58
+ export async function getJudgmentsForPath(filePath, options = {}) {
66
59
  const opts = { ...DEFAULT_OPTIONS, ...options };
67
60
  // Get associated fragment names
68
- const fragmentNames = (0, context_router_js_1.match)(filePath);
61
+ const fragmentNames = contextMatch(filePath);
69
62
  const allFragments = fragmentNames.length > 0 ? fragmentNames : ['general-dev-principles'];
70
63
  // Get judgments for each fragment
71
64
  const allJudgments = [];
@@ -89,7 +82,7 @@ async function getJudgmentsForPath(filePath, options = {}) {
89
82
  // Limit count
90
83
  const limitedJudgments = filteredJudgments.slice(0, opts.maxJudgments);
91
84
  // Calculate overall confidence
92
- const overallConfidence = (0, index_js_1.calculateConfidence)(limitedJudgments);
85
+ const overallConfidence = calculateConfidence(limitedJudgments);
93
86
  // Format as YAML
94
87
  const contextYaml = formatJudgmentsAsYaml(limitedJudgments, opts);
95
88
  return {
@@ -102,8 +95,8 @@ async function getJudgmentsForPath(filePath, options = {}) {
102
95
  /**
103
96
  * Get core judgments for session start (high confidence only)
104
97
  */
105
- async function getCoreJudgmentsForSession(minConfidence = 0.9) {
106
- const allJudgments = await (0, index_js_1.getCombinedJudgments)();
98
+ export async function getCoreJudgmentsForSession(minConfidence = 0.9) {
99
+ const allJudgments = await getCombinedJudgments();
107
100
  const highConfidence = allJudgments
108
101
  .filter(j => j.confidence >= minConfidence && j.source === 'human')
109
102
  .sort((a, b) => b.confidence - a.confidence)
@@ -130,14 +123,14 @@ async function getCoreJudgmentsForSession(minConfidence = 0.9) {
130
123
  /**
131
124
  * Get judgments for a specific context (e.g., "investment", "code-review")
132
125
  */
133
- async function getJudgmentsForContextRequest(context, options = {}) {
126
+ export async function getJudgmentsForContextRequest(context, options = {}) {
134
127
  const opts = { ...DEFAULT_OPTIONS, ...options };
135
- const judgments = await (0, index_js_1.getJudgmentsForContext)(context);
128
+ const judgments = await getJudgmentsForContext(context);
136
129
  const filtered = judgments
137
130
  .filter(j => j.confidence >= opts.minConfidence)
138
131
  .sort((a, b) => b.confidence - a.confidence)
139
132
  .slice(0, opts.maxJudgments);
140
- const overallConfidence = (0, index_js_1.calculateConfidence)(filtered);
133
+ const overallConfidence = calculateConfidence(filtered);
141
134
  const contextYaml = formatJudgmentsAsYaml(filtered, opts);
142
135
  return {
143
136
  fragments: [],
@@ -232,7 +225,7 @@ function escapeYamlString(str) {
232
225
  /**
233
226
  * Generate injection prompt for a file path
234
227
  */
235
- async function generateJudgmentInjection(filePath, gate, options = {}) {
228
+ export async function generateJudgmentInjection(filePath, gate, options = {}) {
236
229
  const opts = { ...DEFAULT_OPTIONS, ...options };
237
230
  // Gate-specific confidence thresholds
238
231
  const gateConfidence = {
@@ -266,4 +259,3 @@ async function generateJudgmentInjection(filePath, gate, options = {}) {
266
259
 
267
260
  ${result.contextYaml}`;
268
261
  }
269
- //# sourceMappingURL=context-router-judgment.js.map
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  /**
3
2
  * Context Router - Port of Bollharness context-fragments to Bolloon
4
3
  *
@@ -7,54 +6,15 @@
7
6
  *
8
7
  * Loads fragments from src/bollharness/scripts/context-fragments/
9
8
  */
10
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
11
- if (k2 === undefined) k2 = k;
12
- var desc = Object.getOwnPropertyDescriptor(m, k);
13
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
14
- desc = { enumerable: true, get: function() { return m[k]; } };
15
- }
16
- Object.defineProperty(o, k2, desc);
17
- }) : (function(o, m, k, k2) {
18
- if (k2 === undefined) k2 = k;
19
- o[k2] = m[k];
20
- }));
21
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
22
- Object.defineProperty(o, "default", { enumerable: true, value: v });
23
- }) : function(o, v) {
24
- o["default"] = v;
25
- });
26
- var __importStar = (this && this.__importStar) || (function () {
27
- var ownKeys = function(o) {
28
- ownKeys = Object.getOwnPropertyNames || function (o) {
29
- var ar = [];
30
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
31
- return ar;
32
- };
33
- return ownKeys(o);
34
- };
35
- return function (mod) {
36
- if (mod && mod.__esModule) return mod;
37
- var result = {};
38
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
39
- __setModuleDefault(result, mod);
40
- return result;
41
- };
42
- })();
43
- Object.defineProperty(exports, "__esModule", { value: true });
44
- exports.CONTEXT_FRAGMENTS = exports.ContextRouter = exports.FALLBACK_FRAGMENTS = exports.CONTEXT_MAP = exports.FRAGMENTS_DIR = exports.BOLLHARNESS_CONTEXT_DIR = void 0;
45
- exports.loadFragment = loadFragment;
46
- exports.match = match;
47
- exports.getFragments = getFragments;
48
- exports.loadFragments = loadFragments;
49
- const fs = __importStar(require("fs"));
50
- const path = __importStar(require("path"));
51
- exports.BOLLHARNESS_CONTEXT_DIR = path.join('src', 'bollharness', 'scripts', 'context-fragments');
52
- exports.FRAGMENTS_DIR = exports.BOLLHARNESS_CONTEXT_DIR;
9
+ import * as fs from 'fs';
10
+ import * as path from 'path';
11
+ export const BOLLHARNESS_CONTEXT_DIR = path.join('src', 'bollharness', 'scripts', 'context-fragments');
12
+ export const FRAGMENTS_DIR = BOLLHARNESS_CONTEXT_DIR;
53
13
  /**
54
14
  * Context Map - Maps file paths to relevant context fragments
55
15
  * Uses actual fragment filenames from src/bollharness/scripts/context-fragments/
56
16
  */
57
- exports.CONTEXT_MAP = {
17
+ export const CONTEXT_MAP = {
58
18
  'src/agents/': ['truth-source-hierarchy', 'protocol-consumers'],
59
19
  'src/documents/': ['truth-source-hierarchy', 'db-shared-structures'],
60
20
  'src/network/': ['truth-source-hierarchy', 'protocol-consumers'],
@@ -71,17 +31,17 @@ exports.CONTEXT_MAP = {
71
31
  /**
72
32
  * Default fragments to inject when no specific match
73
33
  */
74
- exports.FALLBACK_FRAGMENTS = ['general-dev-principles', 'code-quality'];
34
+ export const FALLBACK_FRAGMENTS = ['general-dev-principles', 'code-quality'];
75
35
  /**
76
36
  * Load a context fragment by name
77
37
  */
78
- function loadFragment(name) {
38
+ export function loadFragment(name) {
79
39
  if (!name)
80
40
  return '';
81
- const candidate = path.join(exports.FRAGMENTS_DIR, `${name}.md`);
41
+ const candidate = path.join(FRAGMENTS_DIR, `${name}.md`);
82
42
  try {
83
43
  const resolved = path.resolve(candidate);
84
- const fragmentsDirResolved = path.resolve(exports.FRAGMENTS_DIR);
44
+ const fragmentsDirResolved = path.resolve(FRAGMENTS_DIR);
85
45
  if (!resolved.startsWith(fragmentsDirResolved))
86
46
  return '';
87
47
  if (fs.existsSync(resolved) && fs.statSync(resolved).isFile()) {
@@ -95,7 +55,7 @@ function loadFragment(name) {
95
55
  * Match file path to context fragments
96
56
  * Adapted from bollharness's match() function
97
57
  */
98
- function match(filePath) {
58
+ export function match(filePath) {
99
59
  if (!filePath)
100
60
  return [];
101
61
  if (path.isAbsolute(filePath))
@@ -105,10 +65,10 @@ function match(filePath) {
105
65
  return [];
106
66
  }
107
67
  const matched = [];
108
- const sortedPatterns = Object.keys(exports.CONTEXT_MAP).sort((a, b) => b.length - a.length);
68
+ const sortedPatterns = Object.keys(CONTEXT_MAP).sort((a, b) => b.length - a.length);
109
69
  for (const pattern of sortedPatterns) {
110
70
  if (normalized.startsWith(pattern) || normalized.endsWith(pattern)) {
111
- matched.push(...exports.CONTEXT_MAP[pattern]);
71
+ matched.push(...CONTEXT_MAP[pattern]);
112
72
  }
113
73
  }
114
74
  return [...new Set(matched)];
@@ -116,17 +76,17 @@ function match(filePath) {
116
76
  /**
117
77
  * Get all fragments for a file
118
78
  */
119
- function getFragments(filePath) {
79
+ export function getFragments(filePath) {
120
80
  let fragments = match(filePath);
121
81
  if (!fragments.length) {
122
- fragments = Array.isArray(exports.FALLBACK_FRAGMENTS) ? exports.FALLBACK_FRAGMENTS : [exports.FALLBACK_FRAGMENTS];
82
+ fragments = Array.isArray(FALLBACK_FRAGMENTS) ? FALLBACK_FRAGMENTS : [FALLBACK_FRAGMENTS];
123
83
  }
124
84
  return fragments;
125
85
  }
126
86
  /**
127
87
  * Load all fragments for a file
128
88
  */
129
- function loadFragments(filePath) {
89
+ export function loadFragments(filePath) {
130
90
  const fragmentNames = getFragments(filePath);
131
91
  const contentParts = [];
132
92
  for (const name of fragmentNames) {
@@ -139,12 +99,12 @@ function loadFragments(filePath) {
139
99
  /**
140
100
  * Context Router class for integration with Bolloon
141
101
  */
142
- class ContextRouter {
102
+ export class ContextRouter {
143
103
  fragmentsDir;
144
104
  injectedFile;
145
105
  injectedTTL = 3600; // 1 hour
146
106
  constructor(fragmentsDir) {
147
- this.fragmentsDir = fragmentsDir || exports.FRAGMENTS_DIR;
107
+ this.fragmentsDir = fragmentsDir || FRAGMENTS_DIR;
148
108
  this.injectedFile = path.join('.boll', 'guard', 'injected.json');
149
109
  }
150
110
  /**
@@ -177,7 +137,7 @@ class ContextRouter {
177
137
  */
178
138
  async getJudgmentsForPath(filePath, minConfidence = 0.7) {
179
139
  try {
180
- const { getJudgmentsForPath } = await Promise.resolve().then(() => __importStar(require('./context-router-judgment.js')));
140
+ const { getJudgmentsForPath } = await import('./context-router-judgment.js');
181
141
  const result = await getJudgmentsForPath(filePath, { minConfidence });
182
142
  return result.contextYaml;
183
143
  }
@@ -190,7 +150,7 @@ class ContextRouter {
190
150
  */
191
151
  async getCoreJudgments(minConfidence = 0.9) {
192
152
  try {
193
- const { getCoreJudgmentsForSession } = await Promise.resolve().then(() => __importStar(require('./context-router-judgment.js')));
153
+ const { getCoreJudgmentsForSession } = await import('./context-router-judgment.js');
194
154
  return await getCoreJudgmentsForSession(minConfidence);
195
155
  }
196
156
  catch {
@@ -202,7 +162,7 @@ class ContextRouter {
202
162
  */
203
163
  async getJudgmentsForContext(context, minConfidence = 0.7) {
204
164
  try {
205
- const { getJudgmentsForContextRequest } = await Promise.resolve().then(() => __importStar(require('./context-router-judgment.js')));
165
+ const { getJudgmentsForContextRequest } = await import('./context-router-judgment.js');
206
166
  const result = await getJudgmentsForContextRequest(context, { minConfidence });
207
167
  return result.contextYaml;
208
168
  }
@@ -215,7 +175,7 @@ class ContextRouter {
215
175
  */
216
176
  async generateJudgmentInjection(filePath, gate) {
217
177
  try {
218
- const { generateJudgmentInjection } = await Promise.resolve().then(() => __importStar(require('./context-router-judgment.js')));
178
+ const { generateJudgmentInjection } = await import('./context-router-judgment.js');
219
179
  return await generateJudgmentInjection(filePath, gate);
220
180
  }
221
181
  catch {
@@ -259,12 +219,11 @@ class ContextRouter {
259
219
  fs.writeFileSync(this.injectedFile, JSON.stringify(data, null, 2), 'utf-8');
260
220
  }
261
221
  }
262
- exports.ContextRouter = ContextRouter;
263
222
  /**
264
223
  * Context fragments content
265
224
  * These can be stored in context-fragments/ directory
266
225
  */
267
- exports.CONTEXT_FRAGMENTS = {
226
+ export const CONTEXT_FRAGMENTS = {
268
227
  'general-dev-principles': `# General Development Principles
269
228
 
270
229
  ## Core Values
@@ -581,4 +540,3 @@ Bolloon is a P2P AI document processing system with multi-agent collaboration.
581
540
  - Coordinate with peers
582
541
  - Monitor performance`,
583
542
  };
584
- //# sourceMappingURL=context-router.js.map