Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .github/FUNDING.yml

This file was deleted.

3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
!LICENSE
!README.md
!README_ja.md
!CHANGELOG.md
!CONTRIBUTING.md
!SECURITY.md

Expand Down Expand Up @@ -183,11 +182,9 @@ tests/specs/osato_lms_*

# CI/CD
!.github/
!.github/FUNDING.yml
!.github/workflows/
!.github/workflows/*.yml

# Android companion app
!android/
!android/**
.claude/settings.local.json
25 changes: 12 additions & 13 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
# multi-agent-shogun System Configuration
version: "3.0"
updated: "2026-02-07"
version: "3.1"
updated: "2026-04-19"
description: "Codex CLI + tmux multi-agent parallel dev platform with sengoku military hierarchy"

hierarchy: "Lord (human) → Shogun → Karo → Ashigaru 1-7 / Gunshi"
Expand All @@ -22,7 +22,6 @@ files:
reports: "queue/reports/ashigaru{N}_report.yaml" # Ashigaru → Karo reports
gunshi_report: queue/reports/gunshi_report.yaml # Gunshi → Karo strategic reports
dashboard: dashboard.md # Human-readable summary (secondary data)
daily_log: "logs/daily/YYYY-MM-DD.md" # Karo appends cmd summary on completion. Shogun reads for daily reports.
ntfy_inbox: queue/ntfy_inbox.yaml # Incoming ntfy messages from Lord's phone

cmd_format:
Expand All @@ -49,7 +48,6 @@ mcp_usage: "Lazy-loaded. Always ToolSearch before first use."
parallel_principle: "足軽は可能な限り並列投入。家老は統括専念。1人抱え込み禁止。"
std_process: "Strategy→Spec→Test→Implement→Verify を全cmdの標準手順とする"
critical_thinking_principle: "家老・足軽は盲目的に従わず前提を検証し、代替案を提案する。ただし過剰批判で停止せず、実行可能性とのバランスを保つ。"
bloom_routing_rule: "config/settings.yamlのbloom_routing設定を確認せよ。autoなら家老はStep 6.5(Bloom Taxonomy L1-L6モデルルーティング)を必ず実行。スキップ厳禁。"

language:
ja: "戦国風日本語のみ。「はっ!」「承知つかまつった」「任務完了でござる」"
Expand Down Expand Up @@ -95,15 +93,6 @@ Forbidden after /new: reading instructions/*.md (1st task), polling (F004), cont

Always include: 1) Agent role (shogun/karo/ashigaru/gunshi) 2) Forbidden actions list 3) Current task ID (cmd_xxx)

## Post-Compaction Recovery (CRITICAL)

After compaction, the system instructs "Continue the conversation from where it left off." **This does NOT exempt you from re-reading your instructions file.** Compaction summaries do NOT preserve persona or speech style.

**Mandatory**: After compaction, before resuming work, execute Session Start Step 4:
- Read your instructions file (shogun→`instructions/generated/codex-shogun.md`, etc.)
- Restore persona and speech style (戦国口調 for shogun/karo)
- Then resume the conversation naturally

# Communication Protocol

## Mailbox System (inbox_write.sh)
Expand Down Expand Up @@ -209,6 +198,16 @@ Layer 4: Session context — volatile (AGENTS.md auto-loaded, instructions/*.md,

System manages ALL white-collar work, not just self-improvement. Project folders can be external (outside this repo). `projects/` is git-ignored (contains secrets).

# DesignerRepo Hub Boundary (Codex/Lord workflow)

**UNCONDITIONAL**: When Lord tells Codex to use DesignerRepo, workday files, round files, or Shogun handoff flow, Codex is **hub-only** from that point.

1. **Codex direct implementation edits are FORBIDDEN**: Codex must not directly edit implementation files in the target repository, even for "small", "obvious", or "urgent" fixes.
2. **Codex role is instruction/review only**: Codex must restrict itself to writing or updating DesignerRepo handoff artifacts such as `to_shogun.md`, `from_shogun.md`, `codex_review.md`, `spec.md`, and `closeout.md`, then instruct Shogun what to do.
3. **Always hand off downward**: If work needs to change product code, tests, configs, or app assets, Codex must write precise instructions for Shogun/Karo and stop there until reports come back.
4. **No "results were fine" exception**: Even if a direct edit worked out, that does not legitimize the behavior. Treat any such edit as a workflow violation and immediately return to hub-only mode.
5. **If the request is ambiguous, assume hub-only**: Mention the boundary, update the handoff markdown, and tell Shogun exactly which file to read.

# Shogun Mandatory Rules

1. **Dashboard**: Karo + Gunshi update. Gunshi: QC results aggregation. Karo: task status/streaks/action items. Shogun reads it, never writes it.
Expand Down
57 changes: 0 additions & 57 deletions CHANGELOG.md

This file was deleted.

12 changes: 6 additions & 6 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ files:
reports: "queue/reports/ashigaru{N}_report.yaml" # Ashigaru → Karo reports
gunshi_report: queue/reports/gunshi_report.yaml # Gunshi → Karo strategic reports
dashboard: dashboard.md # Human-readable summary (secondary data)
daily_log: "logs/daily/YYYY-MM-DD.md" # Karo appends cmd summary on completion. Shogun reads for daily reports.
ntfy_inbox: queue/ntfy_inbox.yaml # Incoming ntfy messages from Lord's phone

cmd_format:
required_fields: [id, timestamp, purpose, acceptance_criteria, command, project, priority, status]
purpose: "One sentence — what 'done' looks like. Verifiable."
acceptance_criteria: "List of testable conditions. ALL must be true for cmd=done."
validation: "Karo checks acceptance_criteria at Step 11.7. Ashigaru checks parent_cmd purpose on task completion."
cmd_format:
required_fields: [id, timestamp, purpose, acceptance_criteria, command, project, priority, status, estimated_time]
purpose: "One sentence — what 'done' looks like. Verifiable."
acceptance_criteria: "List of testable conditions. ALL must be true for cmd=done."
estimated_time: "Approximate total time for this cmd (e.g. 30min, 2h). Best-effort estimate by Shogun."
validation: "Karo checks acceptance_criteria at Step 11.7. Ashigaru checks parent_cmd purpose on task completion."

task_status_transitions:
- "idle → assigned (karo assigns)"
Expand Down
18 changes: 0 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1809,22 +1809,6 @@ Even if you're not comfortable with keyboard shortcuts, you can switch, scroll,

---

## Sponsors

This project is funded by sponsors. Your support keeps it free and actively maintained.

<a href="https://github.com/sponsors/yohey-w">
<img src="https://img.shields.io/badge/Sponsor-%E2%9D%A4-ea4aaa?style=for-the-badge&logo=github-sponsors" alt="Sponsor">
</a>

| Tier | Perks |
|------|-------|
| ☕ $5/mo | Name in sponsors section |
| 🏯 $25/mo | Early access to new releases |
| ⚔️ $100/mo | Priority issue/PR response (48h) |
| 🎖️ $500/mo | Monthly 1:1 consultation |
| 🏛️ $1,000/mo | Logo in README + quarterly strategy session |

## Contributing

Issues and pull requests are welcome.
Expand All @@ -1849,6 +1833,4 @@ Based on [Claude-Code-Communication](https://github.com/Akira-Papa/Claude-Code-C

⭐ Star this repo if you find it useful — it helps others discover it.

💖 [Sponsor this project](https://github.com/sponsors/yohey-w) to keep it free.

</div>
18 changes: 0 additions & 18 deletions README_ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -1762,22 +1762,6 @@ tmux respawn-pane -t shogun:0.0 -k 'claude --model opus --dangerously-skip-permi

---

## スポンサー

このプロジェクトはスポンサーによって支えられています。

<a href="https://github.com/sponsors/yohey-w">
<img src="https://img.shields.io/badge/Sponsor-%E2%9D%A4-ea4aaa?style=for-the-badge&logo=github-sponsors" alt="Sponsor">
</a>

| Tier | 特典 |
|------|------|
| ☕ $5/月 | スポンサーセクションに名前掲載 |
| 🏯 $25/月 | 新リリースへの早期アクセス |
| ⚔️ $100/月 | Issue/PRの優先対応(48h以内) |
| 🎖️ $500/月 | 月1回の1on1コンサルテーション |
| 🏛️ $1,000/月 | READMEにロゴ掲載 + 四半期戦略コンサル |

## コントリビューション

Issue、Pull Requestを歓迎します。
Expand All @@ -1804,6 +1788,4 @@ MIT License - 詳細は [LICENSE](LICENSE) を参照。

⭐ 役に立ったらスターをお願いします — 他の人にも見つけてもらえます。

💖 [このプロジェクトをスポンサーする](https://github.com/sponsors/yohey-w)

</div>
35 changes: 5 additions & 30 deletions android/app/src/main/java/com/shogun/android/ssh/SshManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
import com.shogun.android.util.AppLogger
import java.io.File
import java.io.ByteArrayOutputStream
import java.text.SimpleDateFormat
import java.util.Date
Expand Down Expand Up @@ -64,7 +63,7 @@ class SshManager private constructor() {
lastHost = host
lastPort = port
lastUser = user
lastKeyPath = privateKeyPath.trim()
lastKeyPath = privateKeyPath
lastPassword = password
connectInternal()
}
Expand All @@ -74,23 +73,20 @@ class SshManager private constructor() {
return try {
val trimmedPassword = lastPassword.trim()
val jsch = JSch()
val privateKeyIdentity = loadPrivateKeyIdentity()
if (privateKeyIdentity != null) {
val (identityName, privateKeyBytes) = privateKeyIdentity
val passphraseBytes = trimmedPassword.takeIf { it.isNotEmpty() }?.toByteArray()
jsch.addIdentity(identityName, privateKeyBytes, null, passphraseBytes)
if (lastKeyPath.isNotBlank()) {
jsch.addIdentity(lastKeyPath)
}
val newSession = jsch.getSession(lastUser, lastHost, lastPort)
val config = Properties()
config["StrictHostKeyChecking"] = "no"
config["MaxAuthTries"] = "2"
if (privateKeyIdentity != null) {
if (lastKeyPath.isNotBlank()) {
config["PreferredAuthentications"] = "publickey"
} else {
config["PreferredAuthentications"] = "keyboard-interactive,password"
}
newSession.setConfig(config)
if (privateKeyIdentity == null && trimmedPassword.isNotEmpty()) {
if (lastKeyPath.isBlank() && trimmedPassword.isNotEmpty()) {
newSession.setPassword(trimmedPassword)
}
var passwordAttempted = false
Expand Down Expand Up @@ -198,28 +194,16 @@ class SshManager private constructor() {
val channel = s.openChannel("exec") as ChannelExec
channel.setCommand(cmd)
val inputStream = channel.inputStream
val errStream = channel.errStream
channel.connect(5000)
val baos = ByteArrayOutputStream()
val errBaos = ByteArrayOutputStream()
val buffer = ByteArray(4096)
while (true) {
val n = inputStream.read(buffer)
if (n < 0) break
baos.write(buffer, 0, n)
}
// Read any remaining stderr
while (errStream.available() > 0) {
val n = errStream.read(buffer)
if (n < 0) break
errBaos.write(buffer, 0, n)
}
channel.disconnect()
val out = baos.toString("UTF-8")
val err = errBaos.toString("UTF-8")
if (err.isNotBlank()) {
AppLogger.log("SSH", "exec STDERR (${err.length}ch): ${err.take(200)}")
}
AppLogger.log("SSH", "exec OK (${out.length}ch): $shortCmd")
Result.success(out)
} catch (e: Exception) {
Expand Down Expand Up @@ -248,15 +232,6 @@ class SshManager private constructor() {
Result.failure(lastError ?: Exception("再接続失敗(${maxAttempts}回試行)"))
}

private fun loadPrivateKeyIdentity(): Pair<String, ByteArray>? {
val keyPath = lastKeyPath.trim()
if (keyPath.isBlank()) return null

val keyFile = File(keyPath)
require(keyFile.isFile) { "SSH秘密鍵が見つかりませぬ: $keyPath" }
return keyPath to keyFile.readBytes()
}

suspend fun uploadScreenshot(context: Context, imageUri: Uri, projectPath: String = ""): Result<String> =
withContext(Dispatchers.IO) {
sshMutex.withLock {
Expand Down
33 changes: 2 additions & 31 deletions android/app/src/main/java/com/shogun/android/ui/AgentsScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -270,26 +270,14 @@ fun AgentsScreen(

// Rate limit dialog
if (showRateLimitDialog) {
var showRawText by remember { mutableStateOf(false) }
AlertDialog(
onDismissRequest = {
showRateLimitDialog = false
viewModel.clearRateLimitResult()
},
title = {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
SelectionContainer {
Text("Rate Limit Check", color = Kinpaku)
}
if (!rateLimitLoading && rateLimitResult != null) {
TextButton(onClick = { showRawText = !showRawText }) {
Text(if (showRawText) "UI" else "Raw", color = Color(0xFF888888), fontSize = 11.sp)
}
}
SelectionContainer {
Text("Rate Limit Check", color = Kinpaku)
}
},
text = {
Expand All @@ -302,16 +290,6 @@ fun AgentsScreen(
) {
CircularProgressIndicator(color = Kinpaku)
}
} else if (showRawText) {
SelectionContainer {
Text(
text = rateLimitResult ?: "",
color = Zouge,
fontSize = 10.sp,
fontFamily = FontFamily.Monospace,
modifier = Modifier.verticalScroll(rememberScrollState())
)
}
} else {
RateLimitContent(rawText = rateLimitResult ?: "")
}
Expand Down Expand Up @@ -570,20 +548,13 @@ private fun RateLimitContent(rawText: String) {
val claudeMax = data.claudeMax
val codexQuota = data.codexQuota
val codexEntries = data.codexEntries
val hasAnyData = claudeMax.window5h != null || claudeMax.window7d != null ||
codexQuota.account5h != null || codexQuota.model5h != null || codexEntries.isNotEmpty()
SelectionContainer {
Column(
modifier = Modifier
.fillMaxWidth()
.verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.spacedBy(6.dp)
) {
if (!hasAnyData && rawText.isNotBlank()) {
Text("パース失敗 — Raw出力:", color = Color(0xFFCC4444), fontSize = 11.sp)
Text(rawText, color = Zouge, fontSize = 10.sp, fontFamily = FontFamily.Monospace)
}

// ── Claude Max section ──
Text("Claude Max", color = Kinpaku, fontSize = 13.sp, fontFamily = FontFamily.Monospace)
Box(modifier = Modifier.fillMaxWidth().height(1.dp).background(Color(0xFF555555)))
Expand Down
Loading