beeops 0.1.4 → 0.1.5

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/README.md CHANGED
@@ -49,7 +49,7 @@ Attach with `tmux attach -t bo` to watch all agents work in real-time.
49
49
  - **Review Leader** (L2) — Launches review Workers, aggregates findings, approves or requests fixes
50
50
  - **Workers** (L3) — Execute a single subtask: coding, testing, or reviewing
51
51
 
52
- The system includes **12 specialized skills**, **3 hooks** (UserPromptSubmit for context injection, Stop for session logging, PostToolUse for mid-session checkpoints), and **locale support** (en/ja) with a 4-step fallback chain.
52
+ The system includes **10 specialized skills**, **1 hook** (UserPromptSubmit for context injection), and **locale support** (en/ja) with a 4-step fallback chain.
53
53
 
54
54
  Workers receive multi-layer context injection (base + specialization), so each role gets tailored instructions while sharing common autonomous-operation rules.
55
55
 
package/bin/beeops.js CHANGED
@@ -10,9 +10,7 @@ const COMMAND_SRC = path.join(PKG_DIR, "command", "bo.md");
10
10
  const SKILLS_SRC = path.join(PKG_DIR, "skills");
11
11
  const CONTEXTS_SRC = path.join(PKG_DIR, "contexts");
12
12
  const HOOKS_DIR = path.join(PKG_DIR, "hooks");
13
- const HOOK_SRC = path.join(HOOKS_DIR, "prompt-context.py");
14
- const HOOK_STOP_SRC = path.join(HOOKS_DIR, "run-log.py");
15
- const HOOK_POST_SRC = path.join(HOOKS_DIR, "checkpoint.py");
13
+ const HOOK_SRC = path.join(HOOKS_DIR, "bo-prompt-context.py");
16
14
  const HOME_DIR = process.env.HOME || process.env.USERPROFILE;
17
15
 
18
16
  // ── Helpers ──
@@ -184,17 +182,23 @@ function updateSettingsHook(root, mode) {
184
182
 
185
183
  const label = settingsModeLabel(mode);
186
184
 
187
- // UserPromptSubmit: prompt-context.py
188
- const r1 = upsertHook(settings.hooks, "UserPromptSubmit", "prompt-context.py", `python3 ${HOOK_SRC}`);
189
- console.log(` ${r1}: ${label} (UserPromptSubmit hook)`);
190
-
191
- // Stop: run-log.py
192
- const r2 = upsertHook(settings.hooks, "Stop", "run-log.py", `python3 ${HOOK_STOP_SRC}`);
193
- console.log(` ${r2}: ${label} (Stop hook)`);
185
+ // Migrate old hook name (prompt-context.py → bo-prompt-context.py)
186
+ if (settings.hooks.UserPromptSubmit) {
187
+ const oldIdx = settings.hooks.UserPromptSubmit.findIndex((entry) => {
188
+ if (entry.hooks) {
189
+ return entry.hooks.some((h) => h.command && h.command.includes("prompt-context.py") && h.command.includes("beeops"));
190
+ }
191
+ return entry.command && entry.command.includes("prompt-context.py") && entry.command.includes("beeops");
192
+ });
193
+ if (oldIdx >= 0) {
194
+ settings.hooks.UserPromptSubmit.splice(oldIdx, 1);
195
+ console.log(` migrated: removed old prompt-context.py hook`);
196
+ }
197
+ }
194
198
 
195
- // PostToolUse: checkpoint.py
196
- const r3 = upsertHook(settings.hooks, "PostToolUse", "checkpoint.py", `python3 ${HOOK_POST_SRC}`);
197
- console.log(` ${r3}: ${label} (PostToolUse hook)`);
199
+ // UserPromptSubmit: bo-prompt-context.py
200
+ const r1 = upsertHook(settings.hooks, "UserPromptSubmit", "bo-prompt-context.py", `python3 ${HOOK_SRC}`);
201
+ console.log(` ${r1}: ${label} (UserPromptSubmit hook)`);
198
202
 
199
203
  fs.writeFileSync(settingsFile, JSON.stringify(settings, null, 2) + "\n");
200
204
  }
@@ -229,14 +233,6 @@ function init(opts) {
229
233
  path.join(SKILLS_SRC, "bo-issue-sync"),
230
234
  path.join(claudeDir, "skills", "bo-issue-sync")
231
235
  );
232
- copyDir(
233
- path.join(SKILLS_SRC, "bo-log-writer"),
234
- path.join(claudeDir, "skills", "bo-log-writer")
235
- );
236
- copyDir(
237
- path.join(SKILLS_SRC, "bo-self-improver"),
238
- path.join(claudeDir, "skills", "bo-self-improver")
239
- );
240
236
  copyDir(
241
237
  path.join(SKILLS_SRC, "bo-review-backend"),
242
238
  path.join(claudeDir, "skills", "bo-review-backend")
@@ -266,6 +262,7 @@ function init(opts) {
266
262
  for (const old of [
267
263
  "leader-dispatch", "ants-leader-dispatch", "ants-dispatch",
268
264
  "meta-task-decomposer", "orch-issue-sync", "meta-log-writer", "meta-self-improver",
265
+ "bo-log-writer", "bo-self-improver",
269
266
  "review-backend", "review-frontend", "review-database",
270
267
  "review-operations", "review-process", "review-security",
271
268
  ]) {
@@ -282,7 +279,7 @@ function init(opts) {
282
279
  console.log(" removed: .claude/commands/ants.md (migrated to bo.md)");
283
280
  }
284
281
 
285
- // 4. Register hooks (UserPromptSubmit + Stop + PostToolUse)
282
+ // 4. Register hooks (UserPromptSubmit)
286
283
  updateSettingsHook(root, opts.hookMode);
287
284
 
288
285
  // 5. Save locale preference
@@ -344,7 +341,6 @@ function check() {
344
341
  // Check skills
345
342
  const CORE_SKILLS = [
346
343
  "bo-dispatch", "bo-leader-dispatch", "bo-task-decomposer", "bo-issue-sync",
347
- "bo-log-writer", "bo-self-improver",
348
344
  "bo-review-backend", "bo-review-frontend", "bo-review-database",
349
345
  "bo-review-operations", "bo-review-process", "bo-review-security",
350
346
  ];
@@ -366,9 +362,7 @@ function check() {
366
362
  ];
367
363
 
368
364
  const HOOK_CHECKS = [
369
- { hookType: "UserPromptSubmit", matchStr: "prompt-context.py", label: "UserPromptSubmit" },
370
- { hookType: "Stop", matchStr: "run-log.py", label: "Stop" },
371
- { hookType: "PostToolUse", matchStr: "checkpoint.py", label: "PostToolUse" },
365
+ { hookType: "UserPromptSubmit", matchStr: "bo-prompt-context.py", label: "UserPromptSubmit" },
372
366
  ];
373
367
 
374
368
  for (const { hookType, matchStr, label: hookLabel } of HOOK_CHECKS) {
@@ -382,12 +376,8 @@ function check() {
382
376
  }
383
377
  }
384
378
  if (!hookFound) {
385
- if (hookType === "UserPromptSubmit") {
386
- console.log(` [missing] ${hookLabel} hook not found`);
387
- ok = false;
388
- } else {
389
- console.log(` [warn] ${hookLabel} hook not found (optional)`);
390
- }
379
+ console.log(` [missing] ${hookLabel} hook not found`);
380
+ ok = false;
391
381
  }
392
382
  }
393
383
 
@@ -1,54 +1,43 @@
1
1
  {
2
2
  "modes": {
3
- "BO_FB_AGENT": {
4
- "context": ["log.md"],
5
- "skip_log": true,
6
- "description": "beeops: log recording agent (session exit)"
7
- },
8
- "BO_FB_INCLUDE_FB": {
9
- "context": ["fb.md"],
10
- "skip_log": true,
11
- "description": "beeops: log recording + self-improvement (10% chance)",
12
- "append": true
13
- },
14
3
  "BO_QUEEN": {
15
4
  "context": ["queen.md"],
16
- "skip_log": false,
5
+
17
6
  "description": "beeops L1: Queen (orchestrator)"
18
7
  },
19
8
  "BO_LEADER": {
20
9
  "context": ["leader.md"],
21
- "skip_log": false,
10
+
22
11
  "description": "beeops L2: Leader (implementation lead)"
23
12
  },
24
13
  "BO_REVIEW_LEADER": {
25
14
  "context": ["review-leader.md"],
26
- "skip_log": false,
15
+
27
16
  "description": "beeops L2: Review Leader (review lead)"
28
17
  },
29
18
  "BO_WORKER_CODER": {
30
19
  "context": ["worker-base.md", "coder.md"],
31
- "skip_log": false,
20
+
32
21
  "description": "beeops L3: Worker (implementation)"
33
22
  },
34
23
  "BO_WORKER_TESTER": {
35
24
  "context": ["worker-base.md", "tester.md"],
36
- "skip_log": false,
25
+
37
26
  "description": "beeops L3: Worker (test writing)"
38
27
  },
39
28
  "BO_WORKER_CODE_REVIEWER": {
40
29
  "context": ["reviewer-base.md", "code-reviewer.md"],
41
- "skip_log": false,
30
+
42
31
  "description": "beeops L3: Worker (code review)"
43
32
  },
44
33
  "BO_WORKER_SECURITY": {
45
34
  "context": ["reviewer-base.md", "security-reviewer.md"],
46
- "skip_log": false,
35
+
47
36
  "description": "beeops L3: Worker (security review)"
48
37
  },
49
38
  "BO_WORKER_TEST_AUDITOR": {
50
39
  "context": ["reviewer-base.md", "test-auditor.md"],
51
- "skip_log": false,
40
+
52
41
  "description": "beeops L3: Worker (test audit)"
53
42
  }
54
43
  },
@@ -1,54 +1,43 @@
1
1
  {
2
2
  "modes": {
3
- "BO_FB_AGENT": {
4
- "context": ["log.md"],
5
- "skip_log": true,
6
- "description": "beeops: log recording agent (session exit)"
7
- },
8
- "BO_FB_INCLUDE_FB": {
9
- "context": ["fb.md"],
10
- "skip_log": true,
11
- "description": "beeops: log recording + self-improvement (10% chance)",
12
- "append": true
13
- },
14
3
  "BO_QUEEN": {
15
4
  "context": ["queen.md"],
16
- "skip_log": false,
5
+
17
6
  "description": "beeops L1: Queen (orchestrator)"
18
7
  },
19
8
  "BO_LEADER": {
20
9
  "context": ["leader.md"],
21
- "skip_log": false,
10
+
22
11
  "description": "beeops L2: Leader (implementation lead)"
23
12
  },
24
13
  "BO_REVIEW_LEADER": {
25
14
  "context": ["review-leader.md"],
26
- "skip_log": false,
15
+
27
16
  "description": "beeops L2: Review Leader (review lead)"
28
17
  },
29
18
  "BO_WORKER_CODER": {
30
19
  "context": ["worker-base.md", "coder.md"],
31
- "skip_log": false,
20
+
32
21
  "description": "beeops L3: Worker (implementation)"
33
22
  },
34
23
  "BO_WORKER_TESTER": {
35
24
  "context": ["worker-base.md", "tester.md"],
36
- "skip_log": false,
25
+
37
26
  "description": "beeops L3: Worker (test writing)"
38
27
  },
39
28
  "BO_WORKER_CODE_REVIEWER": {
40
29
  "context": ["reviewer-base.md", "code-reviewer.md"],
41
- "skip_log": false,
30
+
42
31
  "description": "beeops L3: Worker (code review)"
43
32
  },
44
33
  "BO_WORKER_SECURITY": {
45
34
  "context": ["reviewer-base.md", "security-reviewer.md"],
46
- "skip_log": false,
35
+
47
36
  "description": "beeops L3: Worker (security review)"
48
37
  },
49
38
  "BO_WORKER_TEST_AUDITOR": {
50
39
  "context": ["reviewer-base.md", "test-auditor.md"],
51
- "skip_log": false,
40
+
52
41
  "description": "beeops L3: Worker (test audit)"
53
42
  }
54
43
  },
@@ -5,13 +5,12 @@ You are an executor agent. You receive a single GitHub Issue and implement it un
5
5
  - **Never ask the user questions or request confirmation.** Make all decisions independently.
6
6
  - Do not use the AskUserQuestion tool.
7
7
  - When uncertain, make a best-effort decision and include the reasoning in the implementation summary.
8
- - If an error occurs, resolve it using `dev-error-resolver`. If unresolvable, output the error details to stdout and terminate.
8
+ - If an error occurs, investigate the root cause and fix it. If unresolvable, output the error details to stdout and terminate.
9
9
 
10
10
  ## Rules
11
11
 
12
12
  - Run `gh issue view {N}` to review the requirements.
13
13
  - **Load project-specific resources**: Before starting implementation, if `.claude/resources.md` exists, read it and follow the project-specific routing, specifications, and design references.
14
- - **Resource routing required**: After task decomposition, before executing each TODO, always consult the `meta-resource-router` routing table and invoke the appropriate skill or agent.
15
14
  - Use `bo-task-decomposer` for task decomposition.
16
15
  - Repeat until completion criteria are met:
17
16
  1. Implement
@@ -58,12 +57,3 @@ concerns: |
58
57
 
59
58
  **Note**: The shell wrapper also auto-generates a basic report (based on exit_code), but without the detailed report the orchestrator cannot understand what was implemented. Always write it.
60
59
 
61
- ## Mandatory Invocation Rules
62
-
63
- When any of the following conditions are met, invoke the corresponding skill or agent without exception.
64
-
65
- | Condition | Resource to Invoke |
66
- | --- | --- |
67
- | Error occurs (TypeError, build failure, etc.) | Skill: `dev-error-resolver` |
68
- | After implementation is complete (changes in git diff) | Agent: `code-reviewer` |
69
- | Domain logic or bug fix implementation | Skill: `dev-tdd-workflow` |
@@ -1,54 +1,43 @@
1
1
  {
2
2
  "modes": {
3
- "BO_FB_AGENT": {
4
- "context": ["log.md"],
5
- "skip_log": true,
6
- "description": "beeops: ログ記録エージェント(セッション終了時)"
7
- },
8
- "BO_FB_INCLUDE_FB": {
9
- "context": ["fb.md"],
10
- "skip_log": true,
11
- "description": "beeops: ログ記録 + 自己改善(10%確率で追加)",
12
- "append": true
13
- },
14
3
  "BO_QUEEN": {
15
4
  "context": ["queen.md"],
16
- "skip_log": false,
5
+
17
6
  "description": "beeops L1: Queen(全体管理)"
18
7
  },
19
8
  "BO_LEADER": {
20
9
  "context": ["leader.md"],
21
- "skip_log": false,
10
+
22
11
  "description": "beeops L2: Leader(実装責任者)"
23
12
  },
24
13
  "BO_REVIEW_LEADER": {
25
14
  "context": ["review-leader.md"],
26
- "skip_log": false,
15
+
27
16
  "description": "beeops L2: Review Leader(レビュー責任者)"
28
17
  },
29
18
  "BO_WORKER_CODER": {
30
19
  "context": ["worker-base.md", "coder.md"],
31
- "skip_log": false,
20
+
32
21
  "description": "beeops L3: Worker(実装)"
33
22
  },
34
23
  "BO_WORKER_TESTER": {
35
24
  "context": ["worker-base.md", "tester.md"],
36
- "skip_log": false,
25
+
37
26
  "description": "beeops L3: Worker(テスト作成)"
38
27
  },
39
28
  "BO_WORKER_CODE_REVIEWER": {
40
29
  "context": ["reviewer-base.md", "code-reviewer.md"],
41
- "skip_log": false,
30
+
42
31
  "description": "beeops L3: Worker(コード品質レビュー)"
43
32
  },
44
33
  "BO_WORKER_SECURITY": {
45
34
  "context": ["reviewer-base.md", "security-reviewer.md"],
46
- "skip_log": false,
35
+
47
36
  "description": "beeops L3: Worker(セキュリティレビュー)"
48
37
  },
49
38
  "BO_WORKER_TEST_AUDITOR": {
50
39
  "context": ["reviewer-base.md", "test-auditor.md"],
51
- "skip_log": false,
40
+
52
41
  "description": "beeops L3: Worker(テスト監査)"
53
42
  }
54
43
  },
@@ -5,13 +5,12 @@
5
5
  - **ユーザーに質問・確認を一切しない**。全て自分で判断して進める。
6
6
  - AskUserQuestion ツールは使用禁止。
7
7
  - 判断に迷う場合はベストエフォートで決定し、実装サマリーに判断理由を含める。
8
- - エラーが起きたら `dev-error-resolver` で自力解決する。解決不能なら stdout にエラー内容を出力して終了する。
8
+ - エラーが起きたら原因を調査して自力修正する。解決不能なら stdout にエラー内容を出力して終了する。
9
9
 
10
10
  ## ルール
11
11
 
12
12
  - `gh issue view {N}` で要件を確認
13
13
  - **プロジェクト固有リソースの読み込み**: 実装開始前に `.claude/resources.md` が存在すれば必ず読み、プロジェクト固有のルーティング・仕様・設計リファレンスに従う
14
- - **リソースルーティング必須**: タスク分解後、各TODOの実行前に `meta-resource-router` のルーティングテーブルを必ず参照し、適切なスキル・エージェントを発動する
15
14
  - タスク分解は `bo-task-decomposer` で行う
16
15
  - 完了条件を満たすまで繰り返す:
17
16
  1. 実装
@@ -57,12 +56,3 @@ concerns: |
57
56
 
58
57
  **注意**: シェルラッパーが基本レポート(exit_code ベース)も自動生成するが、詳細レポートがないと orchestrator は実装内容を把握できない。必ず書くこと。
59
58
 
60
- ## 必須発動ルール
61
-
62
- 以下の条件に合致したら例外なく対応するスキル・エージェントを発動すること。
63
-
64
- | 条件 | 発動リソース |
65
- | --- | --- |
66
- | エラー発生(TypeError, build失敗等) | Skill: `dev-error-resolver` |
67
- | 実装完了後(git diff に変更あり) | Agent: `code-reviewer` |
68
- | ドメインロジック・バグ修正の実装 | Skill: `dev-tdd-workflow` |
@@ -5,13 +5,12 @@ You are an executor agent. You receive a single GitHub Issue and implement it un
5
5
  - **Never ask the user questions or request confirmation.** Make all decisions independently.
6
6
  - Do not use the AskUserQuestion tool.
7
7
  - When uncertain, make a best-effort decision and include the reasoning in the implementation summary.
8
- - If an error occurs, resolve it using `dev-error-resolver`. If unresolvable, output the error details to stdout and terminate.
8
+ - If an error occurs, investigate the root cause and fix it. If unresolvable, output the error details to stdout and terminate.
9
9
 
10
10
  ## Rules
11
11
 
12
12
  - Run `gh issue view {N}` to review the requirements.
13
13
  - **Load project-specific resources**: Before starting implementation, if `.claude/resources.md` exists, read it and follow the project-specific routing, specifications, and design references.
14
- - **Resource routing required**: After task decomposition, before executing each TODO, always consult the `meta-resource-router` routing table and invoke the appropriate skill or agent.
15
14
  - Use `bo-task-decomposer` for task decomposition.
16
15
  - Repeat until completion criteria are met:
17
16
  1. Implement
@@ -58,12 +57,3 @@ concerns: |
58
57
 
59
58
  **Note**: The shell wrapper also auto-generates a basic report (based on exit_code), but without the detailed report the orchestrator cannot understand what was implemented. Always write it.
60
59
 
61
- ## Mandatory Invocation Rules
62
-
63
- When any of the following conditions are met, invoke the corresponding skill or agent without exception.
64
-
65
- | Condition | Resource to Invoke |
66
- | --- | --- |
67
- | Error occurs (TypeError, build failure, etc.) | Skill: `dev-error-resolver` |
68
- | After implementation is complete (changes in git diff) | Agent: `code-reviewer` |
69
- | Domain logic or bug fix implementation | Skill: `dev-tdd-workflow` |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "beeops",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "3-layer multi-agent orchestration system (Queen → Leader → Worker) powered by tmux",
5
5
  "author": "YuugouOhno",
6
6
  "license": "MIT",
package/contexts/en/fb.md DELETED
@@ -1,15 +0,0 @@
1
- You are a self-improvement analysis agent. Execute only the following procedure.
2
-
3
- ## Procedure
4
-
5
- Invoke the `bo-self-improver` skill via the Skill tool to run self-improvement analysis.
6
- Once analysis is complete, exit immediately.
7
-
8
- ## Prohibited
9
-
10
- - Do not continue previous conversation
11
- - Do not make any code changes, design, or planning (only analysis report generation is allowed)
12
-
13
- ## Rules
14
-
15
- - Never delete log JSONL (permanent log)
@@ -1,16 +0,0 @@
1
- You are a dedicated work log recording agent. Execute only the following procedure.
2
-
3
- ## Procedure
4
-
5
- Invoke the `bo-log-writer` skill via the Skill tool to record the log.
6
- Once log recording is complete, exit immediately.
7
-
8
- ## Prohibited
9
-
10
- - Do not continue previous conversation
11
- - Do not make any code changes, design, or planning (only log entry generation is allowed)
12
-
13
- ## Rules
14
-
15
- - Never delete log JSONL (permanent log)
16
- - Log file must be appended to the `$LOG_BASE/log.jsonl` path specified by the skill
package/contexts/fb.md DELETED
@@ -1,15 +0,0 @@
1
- You are a self-improvement analysis agent. Execute only the following procedure.
2
-
3
- ## Procedure
4
-
5
- Invoke the `bo-self-improver` skill via the Skill tool to run self-improvement analysis.
6
- Once analysis is complete, exit immediately.
7
-
8
- ## Prohibited
9
-
10
- - Do not continue previous conversation
11
- - Do not make any code changes, design, or planning (only analysis report generation is allowed)
12
-
13
- ## Rules
14
-
15
- - Never delete log JSONL (permanent log)
package/contexts/ja/fb.md DELETED
@@ -1,15 +0,0 @@
1
- あなたは自己改善分析の専用エージェントです。以下の手順のみ実行してください。
2
-
3
- ## 手順
4
-
5
- `bo-self-improver` スキルを Skill tool で発動して自己改善分析を実行する。
6
- 分析が完了したら即座に終了する。
7
-
8
- ## 禁止事項
9
-
10
- - 前回の会話の続きをしてはならない
11
- - コード変更・設計・計画作成は一切行わない(分析レポートの生成のみ許可)
12
-
13
- ## ルール
14
-
15
- - log JSONL は削除しない(永続ログ)
@@ -1,17 +0,0 @@
1
- あなたは作業ログ記録の専用エージェントです。以下の手順のみ実行してください。
2
-
3
- ## 手順
4
-
5
- `bo-log-writer` スキルを Skill tool で発動してログを記録する。
6
- ログ記録が完了したら即座に終了する。
7
-
8
- ## 禁止事項
9
-
10
- - 前回の会話の続きをしてはならない
11
- - コード変更・設計・計画作成は一切行わない
12
- - log.jsonl 以外のファイル名(log-pending.jsonl 等)でログを作成しない
13
-
14
- ## ルール
15
-
16
- - log JSONL は削除しない(永続ログ)
17
- - ログファイルは必ずスキルが指定する `$LOG_BASE/log.jsonl` に追記する
package/contexts/log.md DELETED
@@ -1,16 +0,0 @@
1
- You are a dedicated work log recording agent. Execute only the following procedure.
2
-
3
- ## Procedure
4
-
5
- Invoke the `bo-log-writer` skill via the Skill tool to record the log.
6
- Once log recording is complete, exit immediately.
7
-
8
- ## Prohibited
9
-
10
- - Do not continue previous conversation
11
- - Do not make any code changes, design, or planning (only log entry generation is allowed)
12
-
13
- ## Rules
14
-
15
- - Never delete log JSONL (permanent log)
16
- - Log file must be appended to the `$LOG_BASE/log.jsonl` path specified by the skill
@@ -1,89 +0,0 @@
1
- #!/usr/bin/env python3
2
- """PostToolUse hook: Mid-session checkpoint logging trigger.
3
-
4
- Fires on every PostToolUse matching Edit/Write/Bash/Skill.
5
- Manages a counter in /tmp/bo-session-checkpoint.json and
6
- outputs a log-recording instruction to stdout when thresholds are reached.
7
-
8
- Thresholds:
9
- - Edit/Write reaches 20 times (since last checkpoint)
10
- - OR 15 minutes elapsed (since last checkpoint) with at least 1 Edit/Write
11
- """
12
-
13
- import json
14
- import os
15
- import sys
16
- import time
17
-
18
- STATE_FILE = "/tmp/bo-session-checkpoint.json"
19
-
20
- # Loop prevention: skip if running inside the feedback/log agent
21
- if os.environ.get("BO_FB_AGENT"):
22
- sys.exit(0)
23
-
24
- # Read hook input from stdin
25
- try:
26
- hook_input = json.load(sys.stdin)
27
- except (json.JSONDecodeError, ValueError):
28
- hook_input = {}
29
-
30
- tool_name = hook_input.get("tool_name", "")
31
- session_id = hook_input.get("session_id", "")
32
-
33
- # Check if this is an Edit/Write call
34
- is_edit_write = tool_name in ("Edit", "Write")
35
-
36
- # Load state file
37
- state = {
38
- "session_id": session_id,
39
- "edits_since_checkpoint": 0,
40
- "last_checkpoint_time": time.time(),
41
- }
42
-
43
- try:
44
- with open(STATE_FILE) as f:
45
- saved = json.load(f)
46
- # Session boundary: reset if session_id changed
47
- if saved.get("session_id") == session_id and session_id:
48
- state = saved
49
- except (FileNotFoundError, json.JSONDecodeError, ValueError):
50
- pass
51
-
52
- # Update counter
53
- if is_edit_write:
54
- state["edits_since_checkpoint"] = state.get("edits_since_checkpoint", 0) + 1
55
-
56
- # Update session ID
57
- state["session_id"] = session_id
58
-
59
- # Threshold check
60
- edits = state.get("edits_since_checkpoint", 0)
61
- elapsed = time.time() - state.get("last_checkpoint_time", time.time())
62
- should_checkpoint = False
63
-
64
- if edits >= 20:
65
- should_checkpoint = True
66
- elif elapsed >= 900 and edits >= 1: # 15 min = 900 sec
67
- should_checkpoint = True
68
-
69
- # Save state
70
- try:
71
- with open(STATE_FILE, "w") as f:
72
- json.dump(state, f)
73
- except OSError:
74
- pass
75
-
76
- # On threshold: output instruction to stdout + reset state
77
- if should_checkpoint:
78
- state["edits_since_checkpoint"] = 0
79
- state["last_checkpoint_time"] = time.time()
80
- try:
81
- with open(STATE_FILE, "w") as f:
82
- json.dump(state, f)
83
- except OSError:
84
- pass
85
-
86
- print("""Mid-session checkpoint: Record work so far to log.jsonl.
87
- 1. Invoke bo-log-writer skill via Skill tool
88
- 2. Record recent changes, decisions, and error resolutions in 1-2 entries
89
- 3. After recording, resume the original task""")