Commit Graph

1462 Commits

Author SHA1 Message Date
Codex
65510e0fc3 test(db): add migration 020 to bootstrap expected-migrations list
Migration 020 (arbiter_intervention_count) was added without updating the
hardcoded expected list in bootstrap.test.ts, breaking its schema-migration
assertions. Add the entry so the canonical `bun run test` suite passes.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-09 02:24:44 +09:00
Codex
de54f13469 fix(paired): bound arbiter interventions to stop infinite arbiter loop
The owner↔reviewer↔arbiter loop could repeat forever: when the arbiter
ruled PROCEED/REVISE/RESET it reset round_trip_count to 0, and nothing
tracked how many times the arbiter had already intervened. A re-deadlock
re-invoked the arbiter without bound.

Add a persistent arbiter_intervention_count (new column + migration 020)
that survives the round-trip reset, and a configurable cap
ARBITER_MAX_INTERVENTIONS (default 1). Once the arbiter has intervened
that many times and the loop still deadlocks, requestArbiterOrEscalate
escalates straight to the user instead of re-invoking the arbiter.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-09 02:15:21 +09:00
Codex
5f06673ac6 style(db): apply prettier formatting to migration 019
Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
2026-06-08 21:38:24 +09:00
Codex
dca56d9493 fix(db): recover progress_text columns skipped by migration-version collision
Merging origin/main collided on schema version 15: the deployment DB
recorded v15 as `reviewer_failure_count` (downstream-only), while upstream
defines v15 as `turn_progress_text`. The runner tracks applied migrations
by version number, so it skips upstream's `turn_progress_text` on the live
DB and never creates paired_turns.progress_text / progress_updated_at —
columns the merged runtime reads and writes (db/paired-turns.ts,
web-dashboard-data.ts), which would crash the live paired-room flow.

Add idempotent migration 019 to re-create those columns under a free
version number. No-op on fresh installs where migration 015 already ran.

Caught by a pre-flight boot of the merged code against a copy of the live DB.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
2026-06-08 21:35:32 +09:00
Codex
1dd948a7ac merge: integrate origin/main (406 commits) into live branch
Merge upstream's paired-room stabilization, dedicated message-runtime-loop,
outbound delivery refactor (ipc-outbound-delivery / deliverFormattedCanonicalMessage),
discord module split, dashboard rework, and migrations 015-018 into our branch.

Conflict policy: prefer upstream for the heavily-refactored paired-room /
message-runtime / db cluster (it supersedes our earlier loop band-aids), keep
only orthogonal unique fixes:
- codex bundled-JS launcher fix (codex-warmup.ts)
- slot-aligned Claude+Codex usage primer (usage-primer.ts) re-wired into index.ts
- MemoryHigh=3G cgroup bound, discord perms diagnostic, prompt docs
- progress null-race + silent-failure publish guards (message-turn-controller.ts)

Dropped (superseded by upstream or unwired): reviewer STEP_DONE/TASK_DONE loop
band-aids, router markdown-escape override, register tribunal-default+git-init,
restart-context rewindToSeq (unwired).

Verified: typecheck clean, build clean, vitest shows zero new regressions vs the
origin/main baseline (only pre-existing env-config failures remain).
2026-06-08 21:15:39 +09:00
Codex
7eb97dd921 fix(primer): resolve bundled codex JS launcher so the periodic primer fires
The Codex usage primer spawned a bare `codex` binary, but under bun/systemd
there is no global `codex` on PATH, so every slot failed with ENOENT and the
primer never ran. Resolve the vendored @openai/codex JS launcher and run it
through the current JS runtime (matching the codex-runner), with global-binary
and PATH fallbacks.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
2026-06-08 15:54:14 +09:00
Codex
8883cd166d fix(gating): drop Codex 'wait until next primer' hold so Codex runs like Claude
The Codex-only shouldHoldFreshCodexUntilPrimer gate blocked fresh Codex
turns outside the dawn window and replied "Codex 사용량 정렬 대기 중...
다음 프라이머 시각 이후 다시 보내주세요", which Claude rooms never did.
The primer (usage-primer.ts) already fires unconditionally for both
providers at 08/13/18/23 KST, so this hold only delayed user turns
without affecting window alignment.

Remove the gate and its now-orphaned helpers (shouldHoldFreshCodexUntilPrimer,
CODEX_ALIGNMENT_AUTO_REPLY, msUntilNextPrimerSlotKST, formatPrimerHourKST,
and the getAllCodexAccounts import). Keep the 04-08 KST dawn alignment gap
block and the usage-exhaustion gate untouched.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
2026-06-08 15:48:04 +09:00
Eyejoker
5c47024e44 feat: add Ray-Ban display dashboard PoC (#226) 2026-06-07 23:05:23 +09:00
Eyejoker
337d46461c fix: split agent runner test quality hotspot (#225) 2026-06-07 23:01:23 +09:00
ejclaw
29ca23a558 fix: release codex lease on readonly prep failure 2026-06-06 18:47:04 +09:00
Codex
80bc078a24 fix(paired): bound reviewer STEP_DONE loop even when arbiter is disabled
The previous fix gated the step_done deadlock guard on the same
deadlockThreshold every verdict uses — but handleReviewerCompletion
passes Infinity for that threshold when no arbiter is configured
(isArbiterEnabled()=false, e.g. production with the ARBITER__AGENT_TYPE
env typo). So step_done never tripped the guard and the
owner TASK_DONE ⇄ reviewer STEP_DONE loop still ran forever.

Give step_done its own always-finite threshold
(stepDoneDeadlockThreshold = ARBITER_DEADLOCK_THRESHOLD) independent of
arbiter availability. Once hit, requestArbiterOrEscalate routes to the
arbiter when enabled, or completes the task with completion_reason
'escalated' (user escalation) when not. Productive REVISE/continue
disagreement still uses deadlockThreshold and is intentionally left on
the existing policy (loops to owner when arbiter is off), matching the
existing "returns reviewer change requests to owner ... deadlock
threshold" test.

Adds a shared regression unit test (deadlockThreshold=Infinity +
step_done still escalates) and three integration tests through
completePairedExecutionContext: arbiter-off+threshold -> escalated,
arbiter-on+threshold -> arbiter_requested, below-threshold -> active.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
2026-06-06 18:11:42 +09:00
Codex
184a8eff6a fix(paired): break reviewer step_done ⇄ owner task_done infinite loop
The reviewer step_done verdict mapped to request_owner_changes
unconditionally, bypassing the deadlock guard that every sibling
verdict respects. When the owner kept replying task_done and the
reviewer kept replying step_done, the room oscillated forever,
spamming duplicate reviewer messages into the channel.

Apply the same `roundTripCount >= deadlockThreshold` guard used by
the done_with_concerns/continue/default branch so step_done
oscillation escalates to the arbiter (or completes via escalation
when no arbiter) instead of looping. Reuses existing round_trip_count
and deadlockThreshold; no migration needed.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
2026-06-06 18:05:12 +09:00
Eyejoker
ac0cd3e41d fix: preserve owner retry failure counts 2026-06-04 22:25:00 +08:00
Eyejoker
1af074786b fix: preserve reviewer delivery follow-ups 2026-06-04 22:24:56 +08:00
Codex
8cf351580b fix(service): bound ejclaw cgroup page cache with MemoryHigh=3G
Per-turn agent runners do heavy file I/O (git clone, builds, ffmpeg/video
scratch) inside the ejclaw service cgroup. The kernel retains those reads as
reclaimable page cache, so systemd's MemoryCurrent climbs to 4-5GB even though
real anon usage stays ~300MB and the host has 13GB free. Add a soft MemoryHigh
so the cache is reclaimed under pressure before the number balloons; MemoryMax
stays unset (infinity) so a legitimate burst is throttled, never OOM-killed.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
2026-06-03 22:24:18 +09:00
Codex
d7b5166862 fix(discord): route >2000-char finals to chunked send, keep editMessage pure
editMessage is called repeatedly by the progress ticker and dashboard
refresh, so appending overflow chunks there duplicated text on every edit.
Revert editMessage to a pure single-message edit and instead expose the
platform per-message cap via Channel.maxMessageLength; deliverOpenWorkItem
now skips the doomed in-place edit and hands the full payload to the
chunking sendMessage path when the final exceeds that cap.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
2026-06-03 22:18:26 +09:00
Codex
c001905678 fix(discord): chunk long editMessage payloads and guard progress null race
- editMessage now splits >2000-char text: edits the tracked message with the
  first chunk and appends the rest as follow-up messages, instead of throwing
  Discord "Invalid Form Body … Must be 2000 or fewer" when promoting a long
  owner result over a progress message.
- syncTrackedProgressMessage captures latestProgressText in a local before the
  editMessage await, fixing a race where a concurrent resetProgressState()
  nulled it and crashed with "null is not an object (this.latestProgressText.length)".
- Add editMessage regression tests (in-place edit vs. chunked overflow).

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
2026-06-03 22:10:26 +09:00
Eyejoker
f1679ac686 [codex] Remove Codex SDK canary runtime (#220)
* Revert "fix: drain sdk follow-up turns (#219)"

This reverts commit 807828e0ce.

* Revert "feat: feature-flag Codex SDK runner (#218)"

This reverts commit 879d16235f.
2026-06-03 19:10:53 +08:00
Eyejoker
807828e0ce fix: drain sdk follow-up turns (#219) 2026-06-03 17:58:24 +08:00
Eyejoker
879d16235f feat: feature-flag Codex SDK runner (#218)
Add optional @openai/codex-sdk exec-backed runner mode behind CODEX_RUNTIME=sdk, with CODEX_RUNTIME_SDK_ROLES canary limiting and app-server fallback for unsupported flows.
2026-06-03 15:31:06 +08:00
Eyejoker
0cbb7e3b9c fix: preserve paired completion errors without leases (#217) 2026-06-03 08:59:51 +08:00
Eyejoker
32468e0214 fix: improve dashboard react doctor score (#215) 2026-06-03 08:30:27 +08:00
Eyejoker
2dab27f443 fix: reduce global react doctor warnings (#214) 2026-06-03 08:30:24 +08:00
Eyejoker
22602da1ec fix: reduce global eslint warnings (#216) 2026-06-03 08:30:21 +08:00
Eyejoker
63a4515241 fix: resume owner after failed reviewer feedback (#208) 2026-06-03 01:37:22 +08:00
Eyejoker
b4197875fa fix: cap codex unavailable recovery loops (#213) 2026-06-03 01:26:57 +08:00
Eyejoker
3d36e15f67 Fix recurring Codex unavailable in paired rooms (#212)
* fix: avoid codex leases for claude readonly sessions

* fix: restore codex lease quality budget

* fix: preserve owner finalization on codex failure

* fix: wake owner after arbiter codex failure

* chore: format readonly codex lease fix
2026-06-03 01:14:39 +08:00
ejclaw
3894d4f406 fix: release Codex lease after final output 2026-06-02 20:51:21 +09:00
Eyejoker
7fc558acb6 fix: restore main quality checks 2026-06-02 18:37:37 +08:00
ejclaw
5648b61075 fix: stop Codex pool retry loops 2026-06-02 05:30:04 +09:00
ejclaw
03d4c81192 fix: recover Codex rotation auth failures
- mark Codex bearer/refresh failures as terminal auth-expired states

- sync refreshed session auth back to rotation slots and revive refreshed dead_auth slots

- stop paired arbiter retry loops when Codex accounts are unavailable

- add regression coverage for rotation leases, follow-up suppression, and arbiter closure
2026-06-02 00:21:53 +09:00
Codex
f28399021a feat(primer): fire Codex primer unconditionally like the Claude primer
Raise CODEX_PRIMER_MAX_USAGE_PCT from 1 to 100 so the Codex usage-window
primer fires at every fixed KST slot regardless of current 5h usage level,
mirroring the Claude primer (which always fires unless rate-limited). The d7
gate stays at 100 so an account whose weekly quota is exhausted is still
skipped, matching Claude's rate-limit skip.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
2026-06-01 16:45:18 +09:00
Codex
f4de795b1e fix(primer): refresh Codex usage before primer and allow 1% fresh accounts
Codex primer was skipping with no_eligible_accounts because it read a
stale usage cache and required exactly 0% usage. Re-query usage right
before the primer call and treat freshly-reset 0~1% accounts as eligible
so the 5h window can be anchored at the fixed KST slot. Also hold new
Codex-owner turns at fresh usage until the next primer slot.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
2026-06-01 16:29:12 +09:00
Codex
db715c6329 style(prompts): prettier format owner paired-room rules
Follow-up to e3c8de6: prettier --check failed on the new section
(missing blank line after the "Before accepting any proposal..."
sentence ahead of the numbered list, and the "Do not include:" header
needed a blank line before the bullets). Running prettier --write
fixes those without changing semantics.

bunx prettier --check prompts/owner-common-paired-room.md → clean.
2026-06-01 10:46:39 +09:00
Codex
90c17c6890 style(scripts): prettier reflow on Discord perms diagnostic
Follow-up to 0d87778; the pre-commit prettier hook rewrapped a few long
console.log lines after the commit landed.
2026-06-01 10:44:51 +09:00
Codex
e3c8de61f1 docs(prompts): require finalize message to be a self-contained answer
The user only sees the final owner message, not the owner↔reviewer
back-and-forth. Recent turns leaked meta-narrative like "리뷰어 지적
반영해서 정정합니다" / "PROCEED 확정" into user-visible replies and
sometimes omitted explicit action items, leaving the user to guess
whether anything was needed from them.

Add a "Finalize message format (self-contained answer)" section to
owner-common-paired-room.md that mandates:
  - direct answer first
  - consolidated recap (no transcript, no narrating disagreement)
  - explicit "사용자 액션 아이템" section, with "없음" when there is
    nothing for the user to do
  - no meta phrases referencing the reviewer loop

The runner reads this prompt fresh per agent spawn
(src/agent-runner-environment.ts), so the change takes effect on the
next owner turn without a service restart.
2026-06-01 10:44:34 +09:00
Codex
0d87778b78 chore(scripts): add Discord bot permission diagnostic
One-off Bun script that logs each configured Discord bot in (owner /
reviewer / arbiter), walks every guild it sees, and prints the bot
member's effective permission bits for the capabilities we plan to
expose (ReadMessageHistory, ManageMessages, ManageChannels,
AddReactions, thread perms, etc.). Used to verify "current permissions
support feature X" empirically instead of guessing from intents.
2026-06-01 10:30:58 +09:00
Codex
047f0d3b70 style(discord): apply prettier reflow to chunker tests
Follow-up to 6505971: the pre-commit prettier hook rewrapped the new
import and an Array.from() call after the commit landed, leaving the
working tree dirty. Commit the reflow so the tree is clean.
2026-06-01 01:25:25 +09:00
Codex
65059719ce fix(discord): preserve fenced code blocks across 2000-char chunks
Long bot replies that exceeded Discord's 2000-char limit were split by a
naive byte-slice loop. When the split fell inside a ```fenced code block
the first chunk lost its closing fence and the next chunk lost its
opener, so Discord rendered raw backticks and the remainder as headings
or bold instead of code.

Replace the slice loop with chunkForDiscord(), a fence-aware splitter
that prefers newline boundaries, re-closes any open fence at the end of
a chunk, and reopens it (with the same language tag) at the start of the
next. Single oversize lines still fall back to a surrogate-pair-safe
byte split. Adds 10 unit tests covering the seam, multi-fence
documents, surrogate pairs, and single-line overflow.
2026-06-01 01:20:28 +09:00
Eyejoker
1ff6b3434f fix: ignore attachment syntax examples (#206) 2026-05-31 22:44:42 +09:00
Eyejoker
b6e7e060cc fix: load supported document attachments (#205) 2026-05-31 22:30:49 +09:00
Eyejoker
778ed9b94a fix: preserve paired input evidence context (#204) 2026-05-31 17:17:38 +09:00
Eyejoker
c0703836e1 fix: surface remaining paired evidence loss (#203) 2026-05-31 16:57:49 +09:00
Eyejoker
239c7ff1e6 fix: make paired evidence loss visible (#202) 2026-05-31 16:20:09 +09:00
Eyejoker
6eca648c47 fix: carry paired turn attachments into review context (#201) 2026-05-31 14:49:56 +09:00
Eyejoker
37b57b20bb refactor: centralize task runtime contracts (#199) 2026-05-30 01:56:41 +09:00
Eyejoker
1531482363 refactor: split Claude agent runner entrypoint (#200) 2026-05-30 01:47:41 +09:00
Eyejoker
35988d9797 fix: use workspace links for runner shared package (#198) 2026-05-30 00:30:31 +09:00
Eyejoker
e3d02dbac1 fix: refresh root deps after runner build (#197) 2026-05-30 00:18:33 +09:00
Eyejoker
46b5543cb5 refactor: centralize host evidence actions (#194) 2026-05-30 00:08:28 +09:00