Commit Graph

520 Commits

Author SHA1 Message Date
Eyejoker
b6dc500daf docs: add ouroboros prompt design attribution to README
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 20:40:50 +09:00
Eyejoker
18d7b315ea chore: clean remaining nanoclaw references from skill files
Update add-compact, add-voice-transcription, customize, and
update-skills SKILL.md files to reference EJClaw instead of NanoClaw.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 19:11:41 +09:00
Eyejoker
2fd4cfc9d0 chore: align setup with EJClaw dual-service architecture 2026-03-26 19:10:07 +09:00
Eyejoker
3efacbdda1 chore: remove legacy nanoclaw CI workflows
Remove bump-version, update-tokens, and merge-forward-skills workflows
inherited from upstream nanoclaw. These require APP_ID/APP_PRIVATE_KEY
secrets not configured for EJClaw and are unnecessary for the current
direct-deploy model. Only ci.yml (PR checks) is retained.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 16:56:13 +09:00
Eyejoker
9152a4ee18 style: format Claude usage cache migration guard 2026-03-26 16:37:38 +09:00
Eyejoker
d865a6b07f fix: stabilize Claude usage cache across token refreshes 2026-03-26 16:37:00 +09:00
Eyejoker
34c9ecd10b docs: update README to reflect current architecture and features
Add multi-account token rotation, provider fallback, CI monitoring,
usage dashboard. Fix Codex description (SDK, not app-server). Add
Authentication section with setup-token instructions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 11:37:30 +09:00
Eyejoker
f79baf1ff8 fix: avoid Claude token refresh races across services 2026-03-26 10:25:09 +09:00
Eyejoker
2b74e6fe40 style: format streamed output evaluator test 2026-03-26 10:13:02 +09:00
Eyejoker
a330ebdf2a fix: suppress Claude 502 provider errors from chat output 2026-03-26 10:11:24 +09:00
Eyejoker
bba19b0c0f docs: clarify Claude internal visibility rules 2026-03-25 23:43:46 +09:00
Eyejoker
8b5624731c docs: add GitHub CI watcher usage guide to platform prompts
Both Claude and Codex platform prompts now include a short
section explaining when to use structured GitHub fields
(ci_provider, ci_repo, ci_run_id) for the host-driven fast
path instead of the generic LLM-per-tick watcher.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 23:19:26 +09:00
Eyejoker
5c2e8e4fdc feat: allow status dashboard header without room details 2026-03-25 23:00:39 +09:00
Eyejoker
c7ba983ea6 feat: show watcher counts in status dashboard header 2026-03-25 22:52:02 +09:00
Eyejoker
20ca6c10fc style: fix prettier formatting in GitHub watcher scheduler tests 2026-03-25 22:44:02 +09:00
Eyejoker
09b4309d96 feat: add GitHub watcher backoff and auto-pause safeguards 2026-03-25 22:43:35 +09:00
Eyejoker
f51f282eb1 chore: update agent-runner package-lock.json
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 22:31:57 +09:00
Eyejoker
57f2045ca6 style: fix prettier formatting in github-ci and scheduler tests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 22:31:52 +09:00
Eyejoker
33fcf9c788 feat: add host-driven GitHub Actions CI watcher (Level 3)
Replace LLM-per-tick polling with direct `gh api` calls for GitHub
Actions watchers. New `ci_provider` discriminator column routes tasks
to either the host-driven path (zero LLM tokens) or the existing
generic LLM path. GitHub watchers poll at 15s intervals (min 10s)
via `checkGitHubActionsRun()` in the scheduler, with completion
messages sent directly to chat on terminal state.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 22:31:42 +09:00
Eyejoker
07c1437055 style: fix prettier formatting in ipc processing loop 2026-03-25 22:00:52 +09:00
Eyejoker
691dbc3310 fix: claim IPC files before processing to avoid duplicates 2026-03-25 22:00:36 +09:00
Eyejoker
fad85ef027 style: fix prettier formatting in db migration 2026-03-25 21:54:27 +09:00
Eyejoker
c3c75882e4 fix: add watcher TTL and cleanup task-scoped artifacts 2026-03-25 21:54:15 +09:00
Eyejoker
113c540f10 style: fix prettier formatting in task-scheduler test 2026-03-25 21:41:08 +09:00
Eyejoker
24d93d5c78 fix: fail fast on missing host IPC dir for task runtimes 2026-03-25 21:40:34 +09:00
Eyejoker
5620301024 fix: pass EJCLAW_HOST_IPC_DIR to MCP server env for both runners
Watcher tasks get task-scoped IPC dirs (data/ipc/{group}/tasks/{taskId}/),
but the MCP server used HOST_IPC_DIR to write IPC files. Without
EJCLAW_HOST_IPC_DIR, it fell back to the task-scoped path, writing
cancel_task/send_message files to nested dirs the IPC watcher never scans.

This caused 11 zombie watchers stuck in infinite loops — self-cancel
calls silently failed with ~4000 stranded IPC files accumulating.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 21:05:22 +09:00
Eyejoker
c89242b6dd fix: harden stripToolCallLeaks regex for CJK/non-ASCII garbage tokens
The previous regex used \w+ for descriptor tokens between the function
name and JSON body, which only matches ASCII word characters. Model
hallucinations often inject CJK/non-ASCII text (e.g. 彩神争霸) in this
position. Switch to (?:\s+[^\s{}]+)+ to match any whitespace-separated
non-brace tokens regardless of character set.

Also removes stale backward-compat re-exports from index.ts and updates
the test import for composeDashboardContent.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 18:06:31 +09:00
Eyejoker
6806001ed6 style: fix prettier formatting after type union refactor
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 17:46:54 +09:00
Eyejoker
94eeaa5e3e refactor: introduce AgentTriggerReason type union as SSOT for error reason strings
Replace scattered reason string literals with a centralized type hierarchy:
- AgentTriggerReason: all possible trigger reasons
- ClaudeRotationReason, CodexRotationReason, NoFallbackCooldownReason:
  derived subtypes for specific contexts
- AgentErrorClassification, FallbackTriggerResult, CodexRotationTriggerResult:
  discriminated unions for compile-time narrowing

Remove dead export isUsageExhausted() (superseded by
isPrimaryNoFallbackCooldownActive). Replace NO_FALLBACK_COOLDOWN_REASONS
Set with isNoFallbackCooldownReason() type guard.

Add tests for agent-error-detection and provider-retry (423 total passing).

Known limitation: 6 `as CodexRotationReason` casts in Codex rotation paths
where streamed trigger reason is AgentTriggerReason but runtime value is
always CodexRotationReason-compatible.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 17:46:43 +09:00
Eyejoker
b86fd1ad89 style: fix prettier formatting in streamed-output-evaluator ternary chain
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 17:24:25 +09:00
Eyejoker
60a9fe86ec fix: detect org-access-denied errors, suppress chat output, and rotate Claude tokens
When a Claude account is suspended, the API returns "Your organization does
not have access to Claude" on the success path or "Failed to authenticate.
API Error: 403 terminated" on the error path. Both are now classified as
'org-access-denied', suppressed from Discord output, and trigger automatic
token rotation. If all tokens are exhausted, enters cooldown without Kimi
fallback (same as usage-exhausted and auth-expired).

Changes:
- agent-error-detection: add isClaudeOrgAccessDeniedMessage(), expand
  classifyClaudeAuthError() and shouldRotateClaudeToken()
- streamed-output-evaluator: detect org-access-denied in success-path chain
- provider-fallback: add NO_FALLBACK_COOLDOWN_REASONS set and
  isPrimaryNoFallbackCooldownActive() helper
- provider-retry: handle org-access-denied in rotation loop
- message-agent-executor / task-scheduler: use generalized no-fallback
  cooldown check
- Tests: +8 test cases across 5 test files (415 total passing)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 17:24:10 +09:00
Eyejoker
3e1e032346 style: fix prettier formatting in formatting tests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 15:51:25 +09:00
Eyejoker
273d52d3da fix: unify agentType value domain to 'claude-code' | 'codex'
The streamed-output-evaluator used 'claude' while the rest of the
codebase used 'claude-code'. Align the evaluator type and all call
sites (message-agent-executor, task-scheduler) to use the canonical
'claude-code' | 'codex' domain consistently.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 15:51:09 +09:00
Eyejoker
8fee2ab3fc fix: strip leaked tool-call serialization text in formatOutbound()
When Codex enters a degenerate loop, it emits tool-call intent as
plaintext (e.g. `to=functions.exec_command code {"cmd":"..."}`) instead
of actual tool calls. Add stripToolCallLeaks() defense layer to remove
these patterns before they reach Discord. Pure garbage output becomes
empty and is suppressed entirely.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 15:51:03 +09:00
Eyejoker
f62aa261e6 refactor: replace boolean trio with explicit RunPhase state machine in GroupQueue
Replace `active/closingStdin/isTaskProcess` booleans with a single `runPhase`
enum (idle | running_messages | running_task | closing_messages). Add
`resetRunState()` to eliminate 7-field reset duplication, and
`assertRunPhaseInvariants()` for runtime validation of field consistency
after every phase transition. Add 3 transition tests covering the full
lifecycle, closeStdin during tasks, and sendMessage phase gating.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 12:55:51 +09:00
Eyejoker
61786cacbf test: add streamed-output-evaluator unit tests
22 tests covering all code paths: success/error forwarding,
Claude banner detection (usage-exhausted, auth-expired), duplicate
trigger suppression, auth error suppression, null-result tracking,
fallback/rotation trigger dispatch, and state immutability.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 12:40:44 +09:00
Eyejoker
fc85fece0f refactor: split unified-dashboard into usage-rows and codex-collector modules
Extract dashboard-usage-rows.ts (UsageRow, formatResetRemaining,
mergeClaudeDashboardAccounts, buildClaudeUsageRows, extractCodexUsageRows)
and codex-usage-collector.ts (fetchCodexUsage, applyCodexUsageToAccount,
buildCodexUsageRowsFromState, refresh functions returning data instead of
mutating module state). unified-dashboard.ts drops from 926 to 563 lines.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 12:32:41 +09:00
Eyejoker
18788f7f91 chore: add state transition logging 2026-03-25 12:16:09 +09:00
Eyejoker
cc7cfbbc5f refactor: centralize visible phase mapping 2026-03-25 12:04:29 +09:00
Eyejoker
1ad23269fa style: format task scheduler 2026-03-25 11:46:58 +09:00
Eyejoker
eebee00e60 refactor: share streamed output evaluation 2026-03-25 11:46:16 +09:00
Eyejoker
03b9480614 fix: prevent typing indicator leak on agent run exceptions and follow-up race
Two leak paths caused Discord typing indicators to persist indefinitely:

1. If runAgent() threw before turnController.finish(), setTyping(false)
   was never called. Wrap the agent run in try/finally to guarantee cleanup.

2. Follow-up message piping called setTyping(true) fire-and-forget. If
   the Promise resolved after finish()'s setTyping(false), the typing
   interval was recreated with nobody to clear it. Await the call to
   serialize the on/off sequence.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 11:18:54 +09:00
Eyejoker
83aedba7f3 Harden usage dashboard and codex auth 2026-03-25 10:40:02 +09:00
Eyejoker
00ffde7623 fix: remove Codex API key auth path, add secret redaction and d7 auto-rotation
- Remove OPENAI_API_KEY from .env and Codex child process env to prevent
  API billing when subscription quota is exhausted
- Remove writeCodexApiKeyAuth entirely — Codex now uses OAuth only
- Add 9-pattern secret redaction in formatOutbound() to prevent key leaks
- Fix Codex usage bucket aggregation: use 'codex' bucket only instead of
  max across all buckets (bengalfox = Codex Spark, not needed)
- Add d7≥100% auto-rotation in updateCodexAccountUsage to skip exhausted
  accounts and prevent API billing fallback
- Add findNextCodexAvailable that checks both rate-limits and d7 usage
- Clean stale apikey auth.json files from all session directories
- Update tests: OAuth-only auth, d7 auto-skip (3 new tests), dashboard

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 10:39:42 +09:00
Eyejoker
094278b08e feat: add ontology checklist, verification gate, completion status protocol, and structured stagnation escalation to paired-room prompts 2026-03-25 07:46:53 +09:00
Eyejoker
2865ba07ce feat: add communication discipline to paired-room prompts (fact-based responses, verification-based completion, 3-strike architecture review) 2026-03-25 07:37:51 +09:00
Eyejoker
7928f2968c fix: always edit progress message for intermediate text
Previously, intermediate text was sent as separate messages when
subagents were active, causing message floods. Now always edit
the progress message regardless of subagent state.
2026-03-25 07:37:49 +09:00
Eyejoker
5e75222754 feat: strengthen paired-room prompts with critical review, consensus gate, and assumption surfacing 2026-03-25 07:31:34 +09:00
Eyejoker
db223f0793 fix: clamp bar() and padName() to prevent negative repeat count
Usage dashboard crashed with RangeError: Invalid count value: -7
when pct exceeded 100 or name exceeded maxNameWidth.
2026-03-25 07:18:04 +09:00
Eyejoker
0af8a7c3f5 fix: restore wide file extension list for inbound attachment parsing
The narrowed list (.txt, .md, .csv, .json, .log) was for outbound,
but was mistakenly applied to inbound. Restore full list for user
file uploads (input direction).
2026-03-25 07:15:24 +09:00