@bolloon/bolloon-agent 0.2.1 → 0.2.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 (118) hide show
  1. package/bin/ipfs +0 -0
  2. package/dist/agents/judgment-protocol.js +479 -0
  3. package/dist/agents/parse-tool-call.js +304 -0
  4. package/dist/agents/pi-sdk.js +190 -267
  5. package/dist/agents/react-loop.js +86 -0
  6. package/dist/agents/session-store.js +157 -0
  7. package/dist/agents/tool-registry.js +136 -0
  8. package/dist/agents/workflow-pivot-loop.js +40 -0
  9. package/dist/bollharness/src/index.js +5 -0
  10. package/dist/bollharness/src/scripts/checks/check_adr_plan_numbering.js +6 -0
  11. package/dist/bollharness/src/scripts/checks/check_api_types.js +45 -0
  12. package/dist/bollharness/src/scripts/checks/check_artifact_link.js +146 -0
  13. package/dist/bollharness/src/scripts/checks/check_bridge_deps.js +6 -0
  14. package/dist/bollharness/src/scripts/checks/check_bugfix_binding.js +6 -0
  15. package/dist/bollharness/src/scripts/checks/check_bugfix_binding_ci.js +6 -0
  16. package/dist/bollharness/src/scripts/checks/check_doc_file_references.js +6 -0
  17. package/dist/bollharness/src/scripts/checks/check_doc_freshness.js +135 -0
  18. package/dist/bollharness/src/scripts/checks/check_doc_links.js +31 -0
  19. package/dist/bollharness/src/scripts/checks/check_file_existence_claims.js +6 -0
  20. package/dist/bollharness/src/scripts/checks/check_fragment_integrity.js +34 -0
  21. package/dist/bollharness/src/scripts/checks/check_hook_installed.js +63 -0
  22. package/dist/bollharness/src/scripts/checks/check_issue_closure.js +41 -0
  23. package/dist/bollharness/src/scripts/checks/check_mcp_parity.js +6 -0
  24. package/dist/bollharness/src/scripts/checks/check_security.js +48 -0
  25. package/dist/bollharness/src/scripts/checks/check_skill_parity.js +6 -0
  26. package/dist/bollharness/src/scripts/checks/check_versions.js +6 -0
  27. package/dist/bollharness/src/scripts/checks/finding.js +13 -0
  28. package/dist/bollharness/src/scripts/checks/next_decision_number.js +20 -0
  29. package/dist/bollharness/src/scripts/checks/regenerate_magic_docs.js +6 -0
  30. package/dist/bollharness/src/scripts/ci/detect_rebaseline_triggers.js +8 -0
  31. package/dist/bollharness/src/scripts/ci/scan_subprocess_cfg.js +8 -0
  32. package/dist/bollharness/src/scripts/ci/scan_verify_artifacts.js +8 -0
  33. package/dist/bollharness/src/scripts/ci/scan_yaml_schema.js +8 -0
  34. package/dist/bollharness/src/scripts/context_router.js +67 -0
  35. package/dist/bollharness/src/scripts/deploy-guard.js +157 -0
  36. package/dist/bollharness/src/scripts/guard-feedback.js +192 -0
  37. package/dist/bollharness/src/scripts/guard_router.js +158 -0
  38. package/dist/bollharness/src/scripts/hooks/_hook_output.js +6 -0
  39. package/dist/bollharness/src/scripts/hooks/auto-python3.js +6 -0
  40. package/dist/bollharness/src/scripts/hooks/deploy-progress-on-session-end.js +6 -0
  41. package/dist/bollharness/src/scripts/hooks/failure-analyzer.js +6 -0
  42. package/dist/bollharness/src/scripts/hooks/gate-judgment-inject.js +92 -0
  43. package/dist/bollharness/src/scripts/hooks/gate-transition-judgment.js +63 -0
  44. package/dist/bollharness/src/scripts/hooks/inbox-ack.js +6 -0
  45. package/dist/bollharness/src/scripts/hooks/inbox-inject-on-start.js +6 -0
  46. package/dist/bollharness/src/scripts/hooks/inbox-validate.js +6 -0
  47. package/dist/bollharness/src/scripts/hooks/inbox-write-ledger.js +6 -0
  48. package/dist/bollharness/src/scripts/hooks/initializer-agent.js +6 -0
  49. package/dist/bollharness/src/scripts/hooks/loop-detection.js +73 -0
  50. package/dist/bollharness/src/scripts/hooks/owner-guard.js +6 -0
  51. package/dist/bollharness/src/scripts/hooks/precompact.js +6 -0
  52. package/dist/bollharness/src/scripts/hooks/review-agent-gatekeeper.js +6 -0
  53. package/dist/bollharness/src/scripts/hooks/risk-tracker.js +108 -0
  54. package/dist/bollharness/src/scripts/hooks/sanitize-on-read.js +6 -0
  55. package/dist/bollharness/src/scripts/hooks/session-reflection.js +7 -0
  56. package/dist/bollharness/src/scripts/hooks/session-start-magic-docs.js +7 -0
  57. package/dist/bollharness/src/scripts/hooks/session-start-reset-risk.js +7 -0
  58. package/dist/bollharness/src/scripts/hooks/session-start-toolkit-reminder.js +7 -0
  59. package/dist/bollharness/src/scripts/hooks/stop-evaluator.js +157 -0
  60. package/dist/bollharness/src/scripts/hooks/tool-call-counter.js +6 -0
  61. package/dist/bollharness/src/scripts/hooks/trace-analyzer.js +10 -0
  62. package/dist/bollharness/src/scripts/install/install-trust-token.js +7 -0
  63. package/dist/bollharness/src/scripts/install/multi_project_registry.js +9 -0
  64. package/dist/bollharness/src/scripts/install/phase2_auto.js +21 -0
  65. package/dist/bollharness/src/scripts/install/pre_commit_installer.js +6 -0
  66. package/dist/bollharness/src/scripts/install/tier_selector.js +7 -0
  67. package/dist/bollharness/src/scripts/install/transcript_miner.js +7 -0
  68. package/dist/bollharness/src/scripts/lib/claim_patterns.js +10 -0
  69. package/dist/bollharness/src/scripts/lib/sanitize_patterns.js +12 -0
  70. package/dist/bollharness/src/scripts/sanitize.js +6 -0
  71. package/dist/constraint-runtime/src/tools/PolymarketSDK/cancelOrder.js +6 -0
  72. package/dist/constraint-runtime/src/tools/PolymarketSDK/createOrder.js +6 -0
  73. package/dist/constraint-runtime/src/tools/PolymarketSDK/getMarket.js +5 -0
  74. package/dist/constraint-runtime/src/tools/PolymarketSDK/getOrders.js +6 -0
  75. package/dist/constraint-runtime/src/tools/PolymarketSDK/listMarkets.js +4 -0
  76. package/dist/constraint-runtime/src/tools/SafeSDK/deploySafe.js +6 -0
  77. package/dist/constraint-runtime/src/tools/WalletTools/autoPay.js +29 -0
  78. package/dist/constraint-runtime/src/tools/WalletTools/createWallet.js +10 -0
  79. package/dist/constraint-runtime/src/tools/WalletTools/getBalance.js +13 -0
  80. package/dist/constraint-runtime/src/tools/WalletTools/importWallet.js +22 -0
  81. package/dist/constraint-runtime/src/tools/WalletTools/sendTransaction.js +25 -0
  82. package/dist/constraint-runtime/src/tools/WalletTools/signMessage.js +10 -0
  83. package/dist/constraint-runtime/src/tools/WalletTools/transferToken.js +25 -0
  84. package/dist/electron/config.js.map +1 -0
  85. package/dist/electron/dialogs.js.map +1 -0
  86. package/dist/electron/first-run.js.map +1 -0
  87. package/dist/electron/ipc.js.map +1 -0
  88. package/dist/electron/logger.js.map +1 -0
  89. package/dist/electron/main.js.map +1 -0
  90. package/dist/electron/menu.js.map +1 -0
  91. package/dist/electron/paths.js.map +1 -0
  92. package/dist/electron/server.js +2 -1
  93. package/dist/electron/server.js.map +1 -0
  94. package/dist/electron/tray.js.map +1 -0
  95. package/dist/electron/window.js.map +1 -0
  96. package/dist/electron-preload.js +29 -0
  97. package/dist/electron-preload.js.map +1 -0
  98. package/dist/electron.js +5 -0
  99. package/dist/electron.js.map +1 -0
  100. package/dist/llm/config-store.js +24 -8
  101. package/dist/llm/pi-ai.js +33 -19
  102. package/dist/workflows/collaboration.js +374 -0
  103. package/dist/workflows/index.js +54 -0
  104. package/package.json +18 -4
  105. package/.comm/README.md +0 -21
  106. package/.comm/default/2026-06-17T08-23-00-017Z-8a735de8.md +0 -7
  107. package/CLAUDE.md +0 -3
  108. package/build/icon.icns +0 -0
  109. package/build/icon.ico +0 -0
  110. package/build/icon.png +0 -0
  111. package/build/tray.png +0 -0
  112. package/build/trayTemplate.png +0 -0
  113. package/scripts/auto-evolve-oneshot.sh +0 -155
  114. package/scripts/auto-evolve-snapshot.sh +0 -136
  115. package/scripts/build-cli.js +0 -216
  116. package/scripts/detect-schema-changes.sh +0 -48
  117. package/scripts/lefthook-helper.sh +0 -69
  118. package/scripts/postinstall.js +0 -153
@@ -0,0 +1,6 @@
1
+ export function main() {
2
+ process.exit(0);
3
+ }
4
+ if (require.main === module) {
5
+ main();
6
+ }
@@ -0,0 +1,6 @@
1
+ export function main() {
2
+ process.exit(0);
3
+ }
4
+ if (require.main === module) {
5
+ main();
6
+ }
@@ -0,0 +1,6 @@
1
+ export function main() {
2
+ process.exit(0);
3
+ }
4
+ if (require.main === module) {
5
+ main();
6
+ }
@@ -0,0 +1,6 @@
1
+ export function main() {
2
+ process.exit(0);
3
+ }
4
+ if (require.main === module) {
5
+ main();
6
+ }
@@ -0,0 +1,6 @@
1
+ export function main() {
2
+ process.exit(0);
3
+ }
4
+ if (require.main === module) {
5
+ main();
6
+ }
@@ -0,0 +1,73 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ const LOOP_THRESHOLD = 5;
4
+ const STATE_DIR = ".boll/guard";
5
+ const STATE_FILE_PREFIX = "loop-";
6
+ const TTL_SECONDS = 3600;
7
+ function getStateFile() {
8
+ const pid = process.ppid;
9
+ return path.join(STATE_DIR, `${STATE_FILE_PREFIX}${pid}.json`);
10
+ }
11
+ function loadState() {
12
+ const stateFile = getStateFile();
13
+ if (!fs.existsSync(stateFile))
14
+ return {};
15
+ try {
16
+ const data = JSON.parse(fs.readFileSync(stateFile, "utf-8"));
17
+ if (Date.now() / 1000 - data._ts > TTL_SECONDS) {
18
+ return {};
19
+ }
20
+ return data;
21
+ }
22
+ catch (exc) {
23
+ process.stderr.write(`[loop-detection] corrupt state ${stateFile}: ${exc}; resetting\n`);
24
+ try {
25
+ fs.unlinkSync(stateFile);
26
+ }
27
+ catch { }
28
+ return {};
29
+ }
30
+ }
31
+ function saveState(state) {
32
+ try {
33
+ if (!fs.existsSync(STATE_DIR)) {
34
+ fs.mkdirSync(STATE_DIR, { recursive: true });
35
+ }
36
+ state._ts = Date.now() / 1000;
37
+ fs.writeFileSync(getStateFile(), JSON.stringify(state), "utf-8");
38
+ }
39
+ catch (exc) {
40
+ process.stderr.write(`[loop-detection] save_state OSError: ${exc}; counter not persisted\n`);
41
+ }
42
+ }
43
+ export function postToolUseInject(message) {
44
+ process.stdout.write(`\n\n## Loop Detection\n\n${message}\n`);
45
+ }
46
+ export function main() {
47
+ let event;
48
+ try {
49
+ event = JSON.parse(fs.readFileSync(0, "utf-8") || "{}");
50
+ }
51
+ catch {
52
+ return;
53
+ }
54
+ const toolName = event.tool_name || "";
55
+ const toolInput = event.tool_input || {};
56
+ if (!["Write", "Edit"].includes(toolName))
57
+ return;
58
+ const filePath = toolInput.file_path || "";
59
+ if (!filePath)
60
+ return;
61
+ const state = loadState();
62
+ const counts = state.counts || {};
63
+ counts[filePath] = (counts[filePath] || 0) + 1;
64
+ state.counts = counts;
65
+ saveState(state);
66
+ const count = counts[filePath];
67
+ if (count >= LOOP_THRESHOLD) {
68
+ postToolUseInject(`[LoopDetection] 你已经编辑 ${filePath} ${count} 次了。考虑换一个方法或退一步重新思考整体方案。[来源: LangChain LoopDetection middleware]`);
69
+ }
70
+ }
71
+ if (require.main === module) {
72
+ main();
73
+ }
@@ -0,0 +1,6 @@
1
+ export function main() {
2
+ process.exit(0);
3
+ }
4
+ if (require.main === module) {
5
+ main();
6
+ }
@@ -0,0 +1,6 @@
1
+ export function main() {
2
+ process.exit(0);
3
+ }
4
+ if (require.main === module) {
5
+ main();
6
+ }
@@ -0,0 +1,6 @@
1
+ export function main() {
2
+ process.exit(0);
3
+ }
4
+ if (require.main === module) {
5
+ main();
6
+ }
@@ -0,0 +1,108 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ const REPO_ROOT = process.cwd();
4
+ const STATE_FILE = path.join(REPO_ROOT, ".boll", "state", "risk-snapshot.json");
5
+ const RISK_ORDER = { R0: 0, R1: 1, R2: 2, R3: 3, R4: 4 };
6
+ const RISK_ELEVATORS = [
7
+ ["scripts/deploy", "R4"],
8
+ ["backend/product/db/migration", "R4"],
9
+ ["Bolloon.md", "R3"],
10
+ [".boll/settings.json", "R3"],
11
+ [".boll/skills/", "R3"],
12
+ [".boll/rules/", "R3"],
13
+ [".boll/agents/", "R3"],
14
+ ["scripts/hooks/", "R3"],
15
+ ["scripts/checks/", "R3"],
16
+ [".github/", "R3"],
17
+ ["backend/product/routes/", "R2"],
18
+ ["backend/product/config.py", "R2"],
19
+ ["backend/server.py", "R2"],
20
+ ["docs/decisions/ADR-", "R2"],
21
+ ["mcp-server/", "R2"],
22
+ ["mcp-server-node/", "R2"],
23
+ ["website/app/", "R2"],
24
+ ];
25
+ function readPayload() {
26
+ try {
27
+ const raw = fs.readFileSync(0, "utf-8");
28
+ return raw ? JSON.parse(raw) : {};
29
+ }
30
+ catch {
31
+ return {};
32
+ }
33
+ }
34
+ function loadSnapshot() {
35
+ if (fs.existsSync(STATE_FILE)) {
36
+ try {
37
+ return JSON.parse(fs.readFileSync(STATE_FILE, "utf-8"));
38
+ }
39
+ catch { }
40
+ }
41
+ return {
42
+ risk_level: "R0",
43
+ risk_sources: [],
44
+ ratchet_locked: false,
45
+ files_touched: [],
46
+ };
47
+ }
48
+ function saveSnapshot(snap) {
49
+ const dir = path.dirname(STATE_FILE);
50
+ if (!fs.existsSync(dir)) {
51
+ fs.mkdirSync(dir, { recursive: true });
52
+ }
53
+ fs.writeFileSync(STATE_FILE, JSON.stringify(snap, null, 2) + "\n", "utf-8");
54
+ }
55
+ function classifyFile(filePath) {
56
+ for (const [pattern, risk] of RISK_ELEVATORS) {
57
+ if (filePath.startsWith(pattern))
58
+ return risk;
59
+ }
60
+ return "R0";
61
+ }
62
+ export function main() {
63
+ const payload = readPayload();
64
+ const toolInput = payload.tool_input || {};
65
+ const filePath = toolInput.file_path || "";
66
+ if (!filePath)
67
+ return;
68
+ let relPath;
69
+ try {
70
+ relPath = path.relative(REPO_ROOT, filePath);
71
+ }
72
+ catch {
73
+ relPath = filePath;
74
+ }
75
+ const fileRisk = classifyFile(relPath);
76
+ const snap = loadSnapshot();
77
+ const currentLevel = snap.risk_level || "R0";
78
+ const currentOrder = RISK_ORDER[currentLevel] ?? 0;
79
+ const newOrder = RISK_ORDER[fileRisk] ?? 0;
80
+ const filesTouched = snap.files_touched || [];
81
+ if (!filesTouched.includes(relPath)) {
82
+ filesTouched.push(relPath);
83
+ }
84
+ let finalRisk = fileRisk;
85
+ let finalOrder = newOrder;
86
+ if (filesTouched.length >= 4 && currentOrder < RISK_ORDER.R1) {
87
+ finalRisk = "R1";
88
+ finalOrder = RISK_ORDER.R1;
89
+ }
90
+ if (finalOrder > currentOrder) {
91
+ snap.risk_level = finalRisk;
92
+ snap.ratchet_locked = true;
93
+ const sources = snap.risk_sources || [];
94
+ sources.push({
95
+ type: "path",
96
+ value: relPath,
97
+ elevated_to: finalRisk,
98
+ ts: new Date().toISOString(),
99
+ });
100
+ snap.risk_sources = sources;
101
+ }
102
+ snap.files_touched = filesTouched;
103
+ snap.last_updated = new Date().toISOString();
104
+ saveSnapshot(snap);
105
+ }
106
+ if (require.main === module) {
107
+ main();
108
+ }
@@ -0,0 +1,6 @@
1
+ export function main() {
2
+ process.exit(0);
3
+ }
4
+ if (require.main === module) {
5
+ main();
6
+ }
@@ -0,0 +1,7 @@
1
+ const REPO_ROOT = process.cwd();
2
+ export function main() {
3
+ process.exit(0);
4
+ }
5
+ if (require.main === module) {
6
+ main();
7
+ }
@@ -0,0 +1,7 @@
1
+ const REPO_ROOT = process.cwd();
2
+ export function main() {
3
+ process.exit(0);
4
+ }
5
+ if (require.main === module) {
6
+ main();
7
+ }
@@ -0,0 +1,7 @@
1
+ const REPO_ROOT = process.cwd();
2
+ export function main() {
3
+ process.exit(0);
4
+ }
5
+ if (require.main === module) {
6
+ main();
7
+ }
@@ -0,0 +1,7 @@
1
+ const REPO_ROOT = process.cwd();
2
+ export function main() {
3
+ process.stdout.write("Session start toolkit reminder.\n");
4
+ }
5
+ if (require.main === module) {
6
+ main();
7
+ }
@@ -0,0 +1,157 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ import { execSync } from "child_process";
4
+ const REPO_ROOT = process.cwd();
5
+ const EVALUATOR_MD = path.join(REPO_ROOT, "scripts", "hooks", "stop-evaluator.md");
6
+ const INITIALIZER_AGENT = path.join(REPO_ROOT, "src", "scripts", "hooks", "initializer-agent.ts");
7
+ const STATE_DIR = path.join(REPO_ROOT, ".boll", "guard");
8
+ const METRICS_DIR = path.join(REPO_ROOT, ".boll", "metrics");
9
+ const TTL_SECONDS = 3600;
10
+ const WRITE_TOOLS = new Set(["Edit", "Write", "NotebookEdit"]);
11
+ function emitMetric(event, sessionKey, data = {}) {
12
+ try {
13
+ if (!fs.existsSync(METRICS_DIR)) {
14
+ fs.mkdirSync(METRICS_DIR, { recursive: true });
15
+ }
16
+ const record = {
17
+ ts: new Date().toISOString(),
18
+ session_key: sessionKey,
19
+ event,
20
+ ...data,
21
+ };
22
+ fs.appendFileSync(path.join(METRICS_DIR, "stop-events.jsonl"), JSON.stringify(record) + "\n", "utf-8");
23
+ }
24
+ catch { }
25
+ }
26
+ function readHookPayload() {
27
+ try {
28
+ const raw = fs.readFileSync(0, "utf-8");
29
+ return raw ? JSON.parse(raw) : {};
30
+ }
31
+ catch {
32
+ return {};
33
+ }
34
+ }
35
+ function getSessionKey(payload) {
36
+ const sid = payload.session_id;
37
+ if (typeof sid === "string" && sid)
38
+ return sid;
39
+ return `ppid-${process.ppid}`;
40
+ }
41
+ function getStateFile(sessionKey) {
42
+ const safe = sessionKey.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 64);
43
+ return path.join(STATE_DIR, `stop-${safe}.flag`);
44
+ }
45
+ function alreadyBlocked(sessionKey) {
46
+ const stateFile = getStateFile(sessionKey);
47
+ if (!fs.existsSync(stateFile))
48
+ return false;
49
+ try {
50
+ const ts = parseFloat(fs.readFileSync(stateFile, "utf-8").trim());
51
+ return Date.now() / 1000 - ts < TTL_SECONDS;
52
+ }
53
+ catch {
54
+ return false;
55
+ }
56
+ }
57
+ function markBlocked(sessionKey) {
58
+ if (!fs.existsSync(STATE_DIR)) {
59
+ fs.mkdirSync(STATE_DIR, { recursive: true });
60
+ }
61
+ fs.writeFileSync(getStateFile(sessionKey), String(Date.now() / 1000), "utf-8");
62
+ }
63
+ function extractEditedFiles(transcriptPath) {
64
+ if (!transcriptPath)
65
+ return null;
66
+ try {
67
+ const files = new Set();
68
+ const content = fs.readFileSync(transcriptPath, "utf-8");
69
+ for (const line of content.split("\n")) {
70
+ if (!line.trim())
71
+ continue;
72
+ try {
73
+ const rec = JSON.parse(line);
74
+ const msg = rec.message || {};
75
+ if (msg.role !== "assistant")
76
+ continue;
77
+ const blocks = msg.content || [];
78
+ for (const block of blocks) {
79
+ if (block.type === "tool_use" && WRITE_TOOLS.has(block.name)) {
80
+ const fp = block.input?.file_path;
81
+ if (fp) {
82
+ try {
83
+ files.add(path.relative(REPO_ROOT, fp));
84
+ }
85
+ catch { }
86
+ }
87
+ }
88
+ }
89
+ }
90
+ catch { }
91
+ }
92
+ return files;
93
+ }
94
+ catch {
95
+ return null;
96
+ }
97
+ }
98
+ function isCompletionCandidate(transcriptPath) {
99
+ const sessionFiles = extractEditedFiles(transcriptPath);
100
+ if (sessionFiles === null)
101
+ return [true, "transcript_unreadable_failopen"];
102
+ if (sessionFiles.size === 0)
103
+ return [false, "no_session_writes"];
104
+ let gitDirty = new Set();
105
+ try {
106
+ const result = execSync("git diff --name-only", { cwd: REPO_ROOT, encoding: "utf-8", timeout: 5000 });
107
+ if (result.trim()) {
108
+ gitDirty = new Set(result.trim().split("\n").filter(l => l));
109
+ }
110
+ }
111
+ catch { }
112
+ const uncommitted = new Set([...sessionFiles].filter(f => gitDirty.has(f)));
113
+ if (uncommitted.size > 0)
114
+ return [true, "uncommitted_session_changes"];
115
+ try {
116
+ const result = execSync("git diff --cached --name-only", { cwd: REPO_ROOT, encoding: "utf-8", timeout: 5000 });
117
+ if (result.trim())
118
+ return [true, "staged_changes"];
119
+ }
120
+ catch { }
121
+ return [false, "all_committed"];
122
+ }
123
+ export function main() {
124
+ const payload = readHookPayload();
125
+ const sessionKey = getSessionKey(payload);
126
+ if (payload.stop_hook_active === true) {
127
+ emitMetric("stop_pass", sessionKey, { reason: "stop_hook_active_guard" });
128
+ process.exit(0);
129
+ }
130
+ if (alreadyBlocked(sessionKey)) {
131
+ emitMetric("stop_pass", sessionKey, { reason: "already_blocked_once" });
132
+ process.exit(0);
133
+ }
134
+ const isCandidate = isCompletionCandidate(payload.transcript_path || "");
135
+ if (!isCandidate[0]) {
136
+ emitMetric("stop_pass", sessionKey, { reason: isCandidate[1] });
137
+ process.exit(0);
138
+ }
139
+ if (!fs.existsSync(EVALUATOR_MD)) {
140
+ emitMetric("stop_skip", sessionKey, { reason: "evaluator_md_missing" });
141
+ process.exit(0);
142
+ }
143
+ try {
144
+ const checklist = fs.readFileSync(EVALUATOR_MD, "utf-8");
145
+ process.stderr.write(checklist + "\n");
146
+ markBlocked(sessionKey);
147
+ emitMetric("stop_block", sessionKey, { reason: `completion_candidate_${isCandidate[1]}` });
148
+ process.exit(2);
149
+ }
150
+ catch {
151
+ emitMetric("stop_skip", sessionKey, { reason: "evaluator_md_read_error" });
152
+ process.exit(0);
153
+ }
154
+ }
155
+ if (require.main === module) {
156
+ main();
157
+ }
@@ -0,0 +1,6 @@
1
+ export function main() {
2
+ process.exit(0);
3
+ }
4
+ if (require.main === module) {
5
+ main();
6
+ }
@@ -0,0 +1,10 @@
1
+ export function main() {
2
+ const args = process.argv.slice(2);
3
+ if (args.includes("--analyze")) {
4
+ process.stdout.write("Trace analysis complete.\n");
5
+ }
6
+ process.exit(0);
7
+ }
8
+ if (require.main === module) {
9
+ main();
10
+ }
@@ -0,0 +1,7 @@
1
+ const REPO_ROOT = process.cwd();
2
+ export function main() {
3
+ process.exit(0);
4
+ }
5
+ if (require.main === module) {
6
+ main();
7
+ }
@@ -0,0 +1,9 @@
1
+ import * as path from "path";
2
+ const REPO_ROOT = process.cwd();
3
+ const REGISTRY_FILE = path.join(REPO_ROOT, ".boll", "install-log.jsonl");
4
+ export function main() {
5
+ process.exit(0);
6
+ }
7
+ if (require.main === module) {
8
+ main();
9
+ }
@@ -0,0 +1,21 @@
1
+ import * as path from "path";
2
+ const REPO_ROOT = process.cwd();
3
+ const TRUST_TOKEN_FILE = path.join(REPO_ROOT, ".boll", "install-trust-token.json");
4
+ export function main() {
5
+ const args = process.argv.slice(2);
6
+ if (args.includes("--install")) {
7
+ const targetProject = args[args.indexOf("--install") + 1];
8
+ if (!targetProject) {
9
+ console.error("Usage: phase2_auto.ts --install <project-path>");
10
+ process.exit(1);
11
+ }
12
+ console.log(`Installing bollharness to ${targetProject}`);
13
+ process.exit(0);
14
+ }
15
+ console.log("bollharness installer");
16
+ console.log("Usage: phase2_auto.ts --install <project-path> [--tier drop-in|adapt|mine]");
17
+ process.exit(0);
18
+ }
19
+ if (require.main === module) {
20
+ main();
21
+ }
@@ -0,0 +1,6 @@
1
+ export function main() {
2
+ process.exit(0);
3
+ }
4
+ if (require.main === module) {
5
+ main();
6
+ }
@@ -0,0 +1,7 @@
1
+ export function selectTier(tier) {
2
+ const validTiers = ["drop-in", "adapt", "mine"];
3
+ if (!validTiers.includes(tier)) {
4
+ return "drop-in";
5
+ }
6
+ return tier;
7
+ }
@@ -0,0 +1,7 @@
1
+ const REPO_ROOT = process.cwd();
2
+ export function main() {
3
+ process.exit(0);
4
+ }
5
+ if (require.main === module) {
6
+ main();
7
+ }
@@ -0,0 +1,10 @@
1
+ export const CLAIM_PATTERNS = [
2
+ /test[s]?\s+(pass|run|complete[ds]?)/gi,
3
+ /all\s+test[s]?\s+(pass|run)/gi,
4
+ /fix(?:ed|es)?\s+the?\s+(bug|issue|problem)/gi,
5
+ /complete[ds]?/gi,
6
+ /done/gi,
7
+ ];
8
+ export function hasUnverifiedClaim(text) {
9
+ return CLAIM_PATTERNS.some(pattern => pattern.test(text));
10
+ }
@@ -0,0 +1,12 @@
1
+ export const SANITIZE_PATTERNS = [
2
+ { pattern: /api[_-]?key["\s:=]+["'][a-zA-Z0-9]{20,}["']/gi, replacement: "***REDACTED***" },
3
+ { pattern: /password["\s:=]+["'][^"']{8,}["']/gi, replacement: "***REDACTED***" },
4
+ { pattern: /secret["\s:=]+["'][a-zA-Z0-9]{16,}["']/gi, replacement: "***REDACTED***" },
5
+ ];
6
+ export function sanitize(text) {
7
+ let result = text;
8
+ for (const { pattern, replacement } of SANITIZE_PATTERNS) {
9
+ result = result.replace(pattern, replacement);
10
+ }
11
+ return result;
12
+ }
@@ -0,0 +1,6 @@
1
+ export function sanitize(text) {
2
+ return text
3
+ .replace(/api[_-]?key["\s:=]+["'][a-zA-Z0-9]{20,}["']/gi, "***REDACTED***")
4
+ .replace(/password["\s:=]+["'][^"']{8,}["']/gi, "***REDACTED***")
5
+ .replace(/secret["\s:=]+["'][a-zA-Z0-9]{16,}["']/gi, "***REDACTED***");
6
+ }
@@ -0,0 +1,6 @@
1
+ export async function cancelOrder(params) {
2
+ return {
3
+ success: false,
4
+ message: 'Polymarket order cancellation requires CLOB client with authentication. Use the Polymarket web interface to cancel orders.',
5
+ };
6
+ }
@@ -0,0 +1,6 @@
1
+ export async function createOrder(params) {
2
+ return {
3
+ success: false,
4
+ message: 'Polymarket order creation requires CLOB client with authentication. Use the Polymarket web interface to create orders.',
5
+ };
6
+ }
@@ -0,0 +1,5 @@
1
+ export async function getMarket(id) {
2
+ const { listMarkets } = await import('polymarket-sdk').catch(() => ({ listMarkets: async () => [] }));
3
+ const markets = await listMarkets({ id });
4
+ return markets[0] ?? null;
5
+ }
@@ -0,0 +1,6 @@
1
+ export async function getOrders(params = {}) {
2
+ return {
3
+ orders: [],
4
+ message: 'Polymarket order retrieval requires CLOB client with authentication. Use the Polymarket web interface to view orders.',
5
+ };
6
+ }
@@ -0,0 +1,4 @@
1
+ export async function listMarkets(params = {}) {
2
+ const { listMarkets: marketsFn } = await import('polymarket-sdk').catch(() => ({ listMarkets: async () => [] }));
3
+ return marketsFn(params);
4
+ }
@@ -0,0 +1,6 @@
1
+ export async function deploySafe(params) {
2
+ return {
3
+ success: false,
4
+ message: 'Safe deployment requires protocol kit with deployer wallet configured.',
5
+ };
6
+ }
@@ -0,0 +1,29 @@
1
+ const autoPayStore = new Map();
2
+ export async function setAutoPay(params) {
3
+ const { Wallet } = await import('ethers');
4
+ const wallet = new Wallet(params.walletPrivateKey);
5
+ const config = {
6
+ enabled: true,
7
+ walletPrivateKey: params.walletPrivateKey,
8
+ rpcUrl: params.rpcUrl ?? 'https://eth.llamarpc.com',
9
+ maxGasPrice: params.maxGasPrice,
10
+ whitelist: params.whitelist,
11
+ };
12
+ autoPayStore.set(params.agentId, config);
13
+ return {
14
+ agentId: params.agentId,
15
+ enabled: true,
16
+ walletAddress: wallet.address,
17
+ rpcUrl: config.rpcUrl,
18
+ };
19
+ }
20
+ export async function getAutoPayConfig(agentId) {
21
+ return autoPayStore.get(agentId) ?? null;
22
+ }
23
+ export async function disableAutoPay(agentId) {
24
+ const config = autoPayStore.get(agentId);
25
+ if (config) {
26
+ config.enabled = false;
27
+ }
28
+ return { agentId, enabled: false };
29
+ }
@@ -0,0 +1,10 @@
1
+ import { Wallet } from 'ethers';
2
+ export async function createWallet() {
3
+ const wallet = Wallet.createRandom();
4
+ return {
5
+ address: wallet.address,
6
+ privateKey: wallet.privateKey,
7
+ mnemonic: wallet.mnemonic?.phrase ?? '',
8
+ createdAt: new Date().toISOString(),
9
+ };
10
+ }
@@ -0,0 +1,13 @@
1
+ import { JsonRpcProvider } from 'ethers';
2
+ export async function getBalance(params) {
3
+ const rpcUrl = params.rpcUrl ?? 'https://eth.llamarpc.com';
4
+ const provider = new JsonRpcProvider(rpcUrl);
5
+ const balance = await provider.getBalance(params.address);
6
+ const balanceEth = Number(balance) / 1e18;
7
+ return {
8
+ address: params.address,
9
+ balance: balance.toString(),
10
+ balanceEth: balanceEth.toFixed(6),
11
+ symbol: 'ETH',
12
+ };
13
+ }