Commit Graph

819 Commits

Author SHA1 Message Date
Eyejoker
e78f0b1968 fix: remove .claude nesting from reviewer session dir path
CLAUDE_CONFIG_DIR included .claude suffix, but the container mounts
the parent directory at /home/node/.claude. This caused double nesting:
/home/node/.claude/.claude/CLAUDE.md — SDK never found the prompts.
2026-03-30 03:20:29 +09:00
Eyejoker
5b8c198e6b fix: remove agent_type filter from getDueTasks for unified service 2026-03-30 03:01:36 +09:00
Eyejoker
96ca9c0655 fix: use in-process Codex usage cache for unified service dashboard 2026-03-30 02:58:28 +09:00
Eyejoker
debcbfccc2 docs: add fallback provider settings to .env.example 2026-03-30 02:56:33 +09:00
Eyejoker
5b8931f94e docs: set recommended model/effort defaults in .env.example 2026-03-30 02:55:48 +09:00
Eyejoker
c7725b1cb4 fix: run Codex usage collection in unified service mode 2026-03-30 02:55:18 +09:00
Eyejoker
c04b1d9a6f docs: update .env.example for unified service architecture 2026-03-30 02:53:55 +09:00
Eyejoker
4b4863330b fix: add debug log for dashboard channel discovery failure 2026-03-30 02:50:37 +09:00
Eyejoker
1031cd44dd refactor: SSOT for paired room prompts, remove 4 duplicate files
All reviewers (claude, codex-review, codex-review-failover) now use
claude-paired-room.md. All owners use owner-common-paired-room.md.

Removed: codex-paired-room.md, codex-review-paired-room.md,
codex-review-failover-paired-room.md, codex-review-platform.md

10 prompt files → 6.
2026-03-30 02:39:04 +09:00
Eyejoker
0c6167f5dc fix: remove hardcoded finalize instructions from turn prompt 2026-03-30 02:35:44 +09:00
Eyejoker
17b60cb10f fix: restore communication discipline details and stagnation pattern names
The anti-pattern guardrails ("It should work now" means run it, etc.)
and stagnation pattern names (Spinning/Oscillation/Diminishing/No progress)
are too useful to compress out — they prevent common LLM failure modes.
2026-03-30 02:33:41 +09:00
Eyejoker
691be0dc86 refactor: streamline paired room prompts and fix role separation
Prompts:
- Remove model-specific names (클코, Codex) — use owner/reviewer only
- Compress duplicated sections (communication, stagnation, consensus)
  while preserving 4 ontological questions and verdict protocol intact
- Remove verdict examples (redundant with status descriptions)
- claude-platform.md: strip SDK defaults, keep only send_message rules

Code:
- Remove reviewer paired room prompt from owner CLAUDE.md
  (was causing role confusion — owner got "You are the reviewer")
- Remove "Provide feedback or approve" from review turn prompt
  (conflicted with CLAUDE.md verdict protocol)

187 lines → 100 lines across 4 prompt files.
2026-03-30 02:31:04 +09:00
Eyejoker
484c0d7316 fix: mount reviewer session dir matching CLAUDE_CONFIG_DIR path
Container mounted data/sessions/{folder}/ but CLAUDE.md was written
to data/sessions/{folder}-reviewer/.claude/ by paired-execution-context.
The reviewer never saw its prompts (verdict protocol, paired room rules).

Now mounts {folder}-reviewer/ to match, so the CLAUDE.md with platform
and paired room prompts is visible inside the container.
2026-03-30 01:50:29 +09:00
Eyejoker
6edf5aebbd refactor: remove explicit paired review command path 2026-03-30 01:43:48 +09:00
Eyejoker
1e9e69ed23 fix: remove duplicate suppression that swallowed final output
The alreadyVisible check compared progress text with final text and
skipped deliverFinalText when they matched. This caused legitimate
final outputs to vanish when the progress message happened to
accumulate the same text through edits.
2026-03-30 01:39:02 +09:00
Eyejoker
aa6477cf2b fix: respect owner verdict during finalize turn
When the reviewer approves (merge_ready) and the owner finalizes,
the system previously only checked for code changes. If the owner
raised concerns (DONE_WITH_CONCERNS, BLOCKED, NEEDS_CONTEXT) during
finalize — e.g. push failed due to detached HEAD — the system
ignored it and auto-completed the task.

Now the owner's verdict is checked first. If the owner raises
concerns, the task goes back to active and re-triggers the reviewer
so the issue can be addressed collaboratively.
2026-03-30 01:37:30 +09:00
Eyejoker
ab2680ba11 feat: route cron output via reviewer bot in paired rooms
In paired rooms, cron output was posted by the owner bot. Since the
owner can't respond to its own messages, the cron report just sat
there with no follow-up action.

Now cron output in paired rooms is posted via the reviewer bot. The
owner picks it up as a peer request, analyzes the report, and acts
on it (e.g., fixing Sentry errors). The normal paired review loop
then kicks in to verify the fix.
2026-03-30 01:32:06 +09:00
Eyejoker
d024b763f0 fix: prepare CLAUDE.md and roomRoleContext for container reviewer
Container reviewer was running without prompts because the container
path in agent-runner.ts skipped prepareGroupEnvironment() entirely.
This meant no CLAUDE.md (platform + paired room prompts + memory
briefing) and no roomRoleContext were passed to the container.

- Add prepareContainerSessionEnvironment() to write CLAUDE.md, sync
  skills, and ensure settings.json for the reviewer session directory
- Pass roomRoleContext through ReviewerContainerInput so the runner
  can prepend the [ROOM_ROLE] header
- Add roomRoleContext field to ReviewerContainerInput interface
2026-03-30 01:12:47 +09:00
Eyejoker
cb66510378 docs: update README with container isolation architecture
- Add container-isolated reviewer, post-approval change detection, credential proxy features
- Update architecture diagram: owner (host process) vs reviewer (Docker container, :ro mount)
- Add Docker to prerequisites
- Update session persistence description (separate sessions per role)
2026-03-30 01:01:10 +09:00
Eyejoker
a215b2471a chore: formatter cleanup and test updates from bot cherry-pick 2026-03-30 00:57:03 +09:00
Eyejoker
5865dea558 fix: route reviewer output to reviewer channel in queued message path
When reviewer was triggered via the normal message dispatch path (not
the review_ready check path), output was sent through the owner channel.
Now checks paired task status to determine the correct output channel.
2026-03-30 00:54:51 +09:00
Eyejoker
13dbf21025 fix: remove snapshot copy from prepareReviewerWorkspaceForExecution
This was the second code path that still called
refreshReviewerSnapshotForPairedTask (file copy). Now returns owner
workspace directly like markPairedTaskReviewReady does.
2026-03-30 00:51:24 +09:00
Eyejoker
6cb0b38ba3 refactor: persistent reviewer containers with docker exec per turn
Instead of docker run --rm per turn (~300ms overhead), containers are
now created once per channel with docker run -d and reused across turns.
Each turn runs via docker exec inside the warm container.

- ensurePersistentContainer: creates or reuses container per channel
- stopReviewerContainer: explicit stop for /clear or shutdown
- Container stays alive with sleep infinity, turns exec node runner
- cleanupOrphans handles stale containers on restart
2026-03-30 00:45:42 +09:00
Eyejoker
42079d5796 refactor: remove host-mode reviewer, container-only
Reviewer always runs in Docker container. No more snapshot file copy —
reviewer mounts the owner workspace directly as read-only. Removes
REVIEWER_CONTAINER_ENABLED toggle and host-mode fallback code.
2026-03-30 00:39:50 +09:00
Eyejoker
53ed437034 fix: handle directory-to-non-directory conflict in copySnapshotPaths
When git ls-files returns directory entries (nested git repos),
cpSync fails trying to overwrite a file placeholder with a directory.
Now removes the conflicting target file before copying.
2026-03-30 00:36:36 +09:00
Eyejoker
09b2ec2b8e fix: skip directories in reviewer snapshot fingerprint to prevent EISDIR
git ls-files can return directory entries (e.g. submodules). readFileSync
on these causes EISDIR error, blocking reviewer trigger for all non-brain
paired channels.
2026-03-30 00:33:44 +09:00
Eyejoker
3899271b9a fix: sync Codex skills to ~/.agents/skills/ instead of .codex/skills/
Codex CLI reads skills from ~/.agents/skills/ (user-level) and
{workDir}/.agents/skills/ (project-level), not from .codex/skills/.
Skills were being copied to the wrong path and never discovered.
2026-03-30 00:26:12 +09:00
Eyejoker
eb40971d4c fix: prevent duplicate final message when progress already shows the same text
When intermediate text was displayed as a progress message and the final
result had the same content, both the progress message and a separate
final message were sent to Discord. Now detects when the progress message
already shows the final text and finalizes in-place without sending a
duplicate.
2026-03-30 00:14:47 +09:00
Eyejoker
60c3dd5fb9 fix: await onOutput chain in container runner to prevent duplicate delivery
Container runner was calling onOutput with fire-and-forget (void),
so work items were still in 'produced' status when the drain loop
checked after container exit. This caused the same message to be
delivered through both reviewer and owner channels.

Now chains onOutput calls and waits for completion before resolving,
matching the host-process runner's outputChain pattern.
2026-03-30 00:05:42 +09:00
Eyejoker
382c9f49d4 fix: bind credential proxy to docker0 interface on Linux
Proxy was binding to 127.0.0.1 which is unreachable from Docker
containers. Now uses PROXY_BIND_HOST (detects docker0 IP on Linux)
so containers can reach the proxy via host.docker.internal.
2026-03-29 23:56:46 +09:00
Eyejoker
6036fd988b fix: remap host paths to container mount points for EJCLAW_WORK_DIR and CLAUDE_CONFIG_DIR
Host paths passed via envOverrides don't exist inside the container,
causing ENOENT when the SDK tries to spawn with a non-existent CWD.
Now remaps EJCLAW_WORK_DIR to /workspace/project and CLAUDE_CONFIG_DIR
to /home/node/.claude (matching the container mount points).
2026-03-29 23:52:32 +09:00
Eyejoker
29ab284c60 fix: use stable per-channel owner worktree to preserve session across tasks
Owner worktree path was per-task (data/workspaces/{folder}/tasks/{taskId}/owner/),
causing Claude SDK to treat each new task as a different project and lose session
context. Now uses a stable per-channel path (data/workspaces/{folder}/owner/).

- Channel isolation preserved (different folders get different worktrees)
- Session persists across tasks (same path = same Claude SDK project)
- Reviewer snapshot still reads from owner worktree correctly
- Fix stale approvedHead reference from cherry-pick conflict
2026-03-29 23:31:14 +09:00
Eyejoker
504be9e41a refactor: use tree hash + git diff for post-approval change detection
- Replace commit hash comparison with git tree hash (HEAD^{tree}) to
  avoid false re-review triggers on commit-only operations
- Use git diff --quiet for actual file change detection
- Update source_ref on failed reviewer execution with done verdict
- Add tests for empty-commit finalize and code-change re-review
- Document Codex reviewer bash mutation gap in reviewer-runtime
2026-03-29 23:24:48 +09:00
Eyejoker
2e4de9cca8 fix: isolate reviewer Claude config dir from owner
Reviewer was picking up owner's cached session from the shared
.claude directory, causing "No conversation found" errors. Now uses
data/sessions/{folder}-reviewer/.claude/ as a separate config dir.
2026-03-29 23:05:24 +09:00
Eyejoker
c28fba0478 feat: re-review on post-approval changes, container improvements
- Compare git HEAD at reviewer approval vs owner finalize to detect
  new code changes after DONE verdict. Re-trigger reviewer if changed,
  complete if unchanged (commit-only is fine).
- Record approved HEAD in source_ref when reviewer says DONE
- Add pnpm store mount, pre-flight checks, idle timeout for containers
- Clean up orphaned containers on shutdown
2026-03-29 23:00:56 +09:00
Eyejoker
b965a7e43d feat: add pnpm store mount, pre-flight checks, and idle timeout for reviewer containers
- Detect pnpm projects and mount global store read-only so hardlinks resolve
- npm/yarn/bun need no extra mounts (node_modules is self-contained)
- Pre-flight check: verify Docker running + image exists (cached after first call)
- Add activity-based idle timeout (reset on stdout/stderr like host runner)
- Clean up orphaned containers on shutdown (not just startup)
2026-03-29 22:46:20 +09:00
Eyejoker
88fa0858ea feat: strengthen reviewer prompts with critical review, completion status, and stagnation awareness
- Expand claude/codex-review paired-room prompts with full review structure
- Add completion status protocol (DONE/DONE_WITH_CONCERNS/BLOCKED/NEEDS_CONTEXT)
- Add stagnation detection (spinning, oscillation, diminishing returns)
- Add communication discipline (fact-based, verification-based)
- Remove <internal> tag instructions from owner platform prompt
- SSOT: all 3 reviewer prompts share the same structure
2026-03-29 22:46:09 +09:00
Eyejoker
8049db0d47 fix: separate reviewer session from owner to preserve review context
Reviewer was starting with undefined sessionId every turn, losing all
conversation context. Now uses `group.folder:reviewer` as the session key
so owner and reviewer maintain independent session histories.

Also updates README to reflect unified service architecture and paired
review workflow.
2026-03-29 22:22:45 +09:00
Eyejoker
33baf2970d fix: strip <internal> tags before verdict detection, add Approved/LGTM as done markers 2026-03-29 21:34:08 +09:00
Eyejoker
b33cf6c058 debug: forward runner query lifecycle logs to INFO for diagnosis 2026-03-29 21:29:06 +09:00
Eyejoker
8119b0bb8f fix: treat execution as success when output was delivered despite null result 2026-03-29 21:24:49 +09:00
Eyejoker
f28b8861bf fix: match verdict markers only at start of first line to prevent false positives 2026-03-29 21:22:45 +09:00
Eyejoker
b8075be92d fix: check reviewer verdict on failed execution to prevent infinite loop 2026-03-29 21:20:16 +09:00
Eyejoker
4f87c840ba refactor: remove /review command and clean up unused imports 2026-03-29 21:17:14 +09:00
Eyejoker
787c05a561 fix: /compact masked by room role header in both runners
prependRoomRoleHeader was called BEFORE /compact detection, turning
"/compact" into "[PAIRED ROOM: owner]\n/compact" which failed the
exact match check. Now session commands are detected first.
2026-03-29 21:14:04 +09:00
Eyejoker
83ddc4faff fix: reset paired task after all session commands to prevent reviewer auto-trigger 2026-03-29 21:09:32 +09:00
Eyejoker
9127841359 fix: /clear resets paired task to prevent reviewer auto-triggering after session clear 2026-03-29 21:07:34 +09:00
Eyejoker
d8cb4b691e feat: verdict-based ping-pong control with merge_ready finalization
- DONE → merge_ready → owner final turn (commit/push) → completed
- DONE_WITH_CONCERNS → active → owner addresses → ping-pong continues
- BLOCKED/NEEDS_CONTEXT → completed (escalate to user, stop ping-pong)
- Regular feedback → active → ping-pong continues
- Owner detects merge_ready status and finalizes autonomously
2026-03-29 20:59:08 +09:00
Eyejoker
16d20fe627 feat: paired review system overhaul — unified service, configurable agents, silent output removal
- Remove UNIFIED_MODE legacy: single service manages all 3 Discord bots
- Add OWNER_AGENT_TYPE / REVIEWER_AGENT_TYPE env vars for configurable agent selection
- Fix Discord channel routing: reviewer output goes through correct bot (discord/discord-review)
- Fix channel name assignment: explicit names prevent agentTypeFilter collision
- Remove silent output suppression system: harness-level protections replace prompt workarounds
- Add reviewer approval detection: DONE marker on first line stops ping-pong
- Include user's original message in reviewer prompt for context
- Fix round_trip_count auto-reset on new user message
- Fix session ID conflict: reviewer doesn't reuse owner's session
- Fix pending progress text flush in runner on close sentinel
- Promote buffered intermediate text to final result when result event has no text
- Remove legacy files: .env.codex.example, .env.codex-review.example, migrate-unify.cjs
- Update CLAUDE.md: server-side build deployment, unified architecture docs
2026-03-29 20:50:32 +09:00
Eyejoker
8a4d83e2c1 fix: let both bots see each other's messages in paired rooms for natural ping-pong 2026-03-29 19:22:01 +09:00