* fix(docker): update Bun base image from 1.2 to 1.3
The lockfile was generated with Bun 1.3.x locally but the Docker image
used oven/bun:1.2-slim. Bun 1.3 changed the lockfile format, causing
--frozen-lockfile to fail during docker build.
* fix(docker): pin Bun to exact version 1.3.9 matching lockfile
Floating tag 1.3-slim resolved to 1.3.11 which has a different lockfile
format than 1.3.9 used to generate bun.lock. Pin to exact patch version
to prevent --frozen-lockfile failures.
* fix(docker): add missing docs-web workspace package.json
The docs-web package was added as a workspace member but its
package.json was never added to the Dockerfile COPY steps. This caused
bun install --frozen-lockfile to fail because the workspace layout
in Docker didn't match the lockfile.
* fix(docker): use hoisted linker for Vite/Rollup compatibility
Bun's default "isolated" linker stores packages in node_modules/.bun/
with symlinks that Vite's Rollup bundler cannot resolve during
production builds (e.g., remark-gfm → mdast-util-gfm chain).
Using --linker=hoisted gives the classic flat node_modules layout
that Rollup expects. Local dev is unaffected (Vite dev server handles
the isolated layout fine).
* ci: pin Bun version to 1.3.9 and add Docker build check
- Align CI Bun version (was 1.3.11) with Dockerfile and local dev
(1.3.9) to prevent lockfile format mismatches between environments
- Add docker-build job to test.yml that builds the Docker image on
every PR — catches Dockerfile regressions (missing workspace
packages, linker issues, build failures) before they reach deploy
* fix(ci): add permissions for GHA cache and tighten Bun engine
- Add actions: write permission to docker-build job so GHA layer cache
writes succeed on PRs from forks
- Tighten package.json engines.bun from >=1.0.0 to >=1.3.9 to document
the minimum version that matches the lockfile format
* fix(ci): add smoke test, align Bun version across all workflows
Review fixes:
- Add load: true + health endpoint smoke test to docker-build CI job
so we verify the image actually starts, not just compiles
- Align Bun 1.3.9 in deploy-docs.yml and release.yml (were still 1.3.11)
- Document why docs-web source is intentionally omitted from Docker
* chore: float Docker to bun:1.3 and align CI to 1.3.11
- Dockerfile: oven/bun:1.3-slim (auto-tracks latest 1.3.x patches)
- CI workflows: bun-version 1.3.11 (current latest, reproducible)
- engines.bun: >=1.3.9 (minimum for local devs)
Lockfile format is stable across 1.3.x patches, so this is safe.
* fix(docker,ci): pin Docker to 1.3.11, loosen engines, harden smoke test
- Dockerfile: pin oven/bun:1.3.11-slim (was floating 1.3-slim) so Docker
builds are reproducible and match CI exactly.
- package.json: loosen engines to ^1.3.0 so end users on any 1.3.x can
run the CLI; CI/Docker remain pinned to the canonical latest.
- CI smoke test: replace 'sleep 5' with curl --retry-connrefused, and
move container cleanup to an 'if: always()' step so a failed health
check no longer leaks the named container.
---------
Co-authored-by: Rasmus Widing <rasmus.widing@gmail.com>
The test suite took ~131s because retry/reconnect tests waited on real
setTimeout delays (2-8s per retry). Make each delay injectable via
constructor options so tests can pass 1ms, and add --parallel to run
package test batches concurrently.
Changes:
- Add --parallel flag to root test script for concurrent package runs
- Add retryBaseDelayMs option to ClaudeClient and CodexClient constructors
- Add graceMs param to SSETransport constructor
- Add retryDelayMs option to GitHub and Gitea adapter constructors
- Update all retry/reconnect tests to use 1ms delays
- Add delay_ms: 1 to DAG executor retry test nodes
- Reduce test timeouts from 30-60s to 1-5s
Fixes#1008
- Move website/ → packages/docs-web/ as @archon/docs-web
- Remove npm package-lock.json, use shared bun.lock
- Update deploy-docs.yml to use bun instead of npm
- Add dev:docs and build:docs workspace scripts
- Update prettierignore and eslint ignores
- Update Starlight edit link base URL
* Add Pino structured logging infrastructure (Phase 1)
Install pino/pino-pretty, create createLogger() factory in @archon/core
with module-scoped child loggers, setLogLevel()/getLogLevel() runtime
control, and TTY-aware pretty/JSON output. Wire up --quiet/-q and
--verbose/-v CLI flags, LOG_LEVEL env var in server entry point, and
update CLAUDE.md logging guidelines. No console.log migration yet —
that's Phase 2-3.
* Address PR review: fix crash, incorrect docs, and test gaps
- Wrap setLogLevel() in try-catch in server startup (prevents crash on
invalid LOG_LEVEL env var)
- Fix incorrect JSDoc claiming level propagates to existing children
(Pino only affects children created after the change)
- Add console.warn when LOG_LEVEL env var is set but invalid
- Move CLI setLogLevel calls inside try-catch block
- Re-export Logger type through ./utils/logger (not directly from pino)
- Document all 6 Pino log levels (add fatal/trace) in CLAUDE.md and
module docblock
- Update CLAUDE.md error handling examples to use Pino convention
- Fix CLI help text: --quiet "Reduce log verbosity" (not "suppress all")
- Add LOG_LEVEL to .env.example
- Add 5 CLI flag parsing tests for --quiet/-q and --verbose/-v
- Sync parseCliArgs test helper with actual cli.ts options
* Migrate AI clients and GitHub adapter to Pino logging
Replace all console.log/error/warn calls in claude.ts, codex.ts, and
github.ts with structured Pino logging. Add shared mock logger helper
for test files. Uses lazy-init getLog() pattern in core packages to
support test mocking.
* Migrate all console.log/error/warn to Pino structured logging
Replace ~530 console calls across 44 files with structured Pino
logging. This completes Phases 2-3 of the logging migration (#321).
Production code (core + server):
- Workflow engine (executor, loader, logger, event-emitter)
- Orchestrator
- Command handler + clone
- Database layer (6 files)
- Isolation + cleanup service
- Utilities + config (11 files)
- Server entry point + all platform adapters
- Web adapter + API routes
CLI: Only diagnostic logging converted; user-facing output (help,
version, workflow list) remains as console.log by design.
Test updates:
- Mock logger via createMockLogger() + mock.module pattern
- Fix Bun test-ordering issues (mock.module leaks between files
in single-process runner)
Zero console.log/error/warn remaining in production code (only
logger.ts bootstrap warning and scripts/setup-auth.ts by design).
* docs: update stale console.log references to Pino logging
Replace old console.log/error/warn patterns in documentation examples
with Pino structured logging patterns to match implementation.
Updated files:
- docs/architecture.md: Updated all code examples
- docs/cli-developer-guide.md: Updated adapter description
- docs/worktree-orchestration-research.md: Updated orchestrator examples
* Address PR review findings: fix quiet flag, webhook logging, exports
- Change --quiet flag to set log level 'warn' (not 'error') to avoid
suppressing degradation warnings silently
- Add diagnostic context (signature prefix, payload size) to webhook
signature failure log for debuggability
- Remove rootLogger from @archon/core public exports to enforce
encapsulation via setLogLevel/getLogLevel API
- Remove redundant setLogLevel() call in server startup since
rootLogger already reads LOG_LEVEL at module initialization
* Migrate remaining console calls in core packages to Pino
- executor.ts: base branch resolution logging
- sqlite.ts: session column migration warning
* Fill logging gaps: add loggers to 5 DB modules, fix patterns, unify lazy init
- Add Pino loggers to db/sessions, codebases, isolation-environments,
messages, and command-templates (all were missing)
- Fix missing err object in orchestrator isolation_link_failed log
- Fix SSE heartbeat using { error: msg } instead of { err } pattern
- Add missing context (channelId, threadTs) to Discord/Slack error logs
- Convert all server package files from eager to lazy getLog() pattern
for consistent test mock interception
- Add debug log to client factory for provider selection
- Add Pino logging to CLI isolation.ts catch blocks
- Fix workflow.ts natural-language warning to snake_case event
- Add logger mocks to 10 test files to suppress noisy output
- Expand logger.test.ts with trace/fatal and edge case coverage
Bun auto-loads .env from CWD before any user code runs. When the CLI
is invoked from a target repo that has DATABASE_URL in its .env, the
CLI connects to that app's database instead of using Archon's SQLite.
Fix by:
- Deleting DATABASE_URL from process.env before loading ~/.archon/.env
- Adding override:true to dotenv config() so ~/.archon/.env always wins
- Removing --env-file=.env from the cli script in package.json
* Archon UI PRD and phase 1 plan
* Initial Archon UI
* Workflow tracking
* UI improvements (with a couple schema changes)
* Message history for web adapter and UI adjustments
* Chat/Project/Tasks in Archon UI
* UI fixes
* UI fixes
* UI improvements
* Fix PR review issues: type safety, error handling, cleanup, docs
- Convert MessageChunk to discriminated union with workflow_dispatch variant
- Add IWebPlatformAdapter interface and isWebAdapter() type guard
- Replace unsafe 'in' type guards with proper type narrowing in orchestrator
- Add logging to silent catch blocks in api.ts, web.ts
- Add WebAdapter buffer cleanup with 60s delayed cleanup on disconnect
- Wrap SQLite migration ALTER TABLE groups in try/catch
- Log SSE parse errors in useSSE.ts
- Truncate API error bodies to 200 chars, include URL path
- Surface background workflow errors to parent conversation
- Fix getWorkflowRunByWorker to only swallow 404s, re-throw 500s
- Add documentation comments to ChatMessage and SSEEvent types
- Update table counts from 3/5/6 to 8 across all docs
* Remove agent plan files from PR, gitignore .agents/plans/
These are local development artifacts that shouldn't be in the repo.
* Gitignore .claude/PRPs/
* Fix PR review issues: error handling, type safety, silent failures
- Fix acquireLock error swallowing: wrap handler in try/catch/finally to
always release UI lock and surface errors to SSE stream
- Restrict CORS to configurable origin (WEB_UI_ORIGIN env var)
- Validate status query param instead of unsafe `as` cast
- Add per-codebase JSON.parse error isolation for corrupted commands
- Type request body in POST /api/conversations
- Return 404 for missing conversation instead of empty array
- Add warning log when flushAssistantMessage has no DB ID mapping
- Add debug logging to 6 SSE catch blocks (was silently swallowing)
- Replace 17x .catch(() => undefined) with void on fire-and-forget calls
- Make workflow status='running' update a blocking error
- Split MessageChunk into proper per-type discriminated union
- Add hidden field to Conversation interface
- Add guard in addMessage for undefined row
- Extract WorkflowRunStatus/WorkflowStepStatus type aliases
- Fix WorkflowArtifact.type to use literal union
- Separate SSE parse errors from handler errors in useSSE hook
- Gitignore e2e testing session artifact
* Wire up dead endpoints: workflow run UI, health display, worker→run link
- Extract dispatchToOrchestrator() helper to deduplicate lock/dispatch
logic between message send and workflow run endpoints
- Fix workflow run endpoint to construct /workflow run <name> <msg>
from URL param + body, with name validation
- Add run panel to WorkflowList with message input, error display,
and navigation to chat on success
- Add System Health section to SettingsPage with independent query
and actionable error messages
- Add worker→run navigation link in WorkflowExecution header
- Regenerate 000_combined.sql to include migrations 001-015
- Fix silent .catch() patterns: log errors instead of swallowing
- Wrap emitSSE in catch block, log full error objects
* Fix routing for conversation IDs with special characters
GitHub issue conversation IDs like "user/repo#42" contain / and #
which break React Router's :param matching. Fix by:
- Use /chat/* splat route instead of /chat/:conversationId
- encodeURIComponent() all platform_conversation_id values in URLs
- decodeURIComponent() in ChatPage when reading the splat param
* Restructure sidebar: project selector nav, remove dead components
Replace multi-view sidebar (ChatView, ProjectView, TaskView, ViewSwitcher)
with a simpler project-scoped navigation. Add ProjectSelector component
for switching between codebases. Remove unused ConversationsList,
useNotifications hook, and related dead code.
* Add project CRUD: clone/register from UI, delete with cleanup
Extract clone logic from command-handler into standalone clone.ts module
with cloneRepository() and registerRepository() entry points. Add REST
endpoints POST /api/codebases (clone URL or register local path) and
DELETE /api/codebases/:id (destroy worktrees, unlink DB, remove workspace).
Update sidebar with "+" button for inline project add input that auto-detects
URL vs local path, and hover-to-delete with AlertDialog confirmation on each
project in ProjectSelector.
* Harden backend guard rails, polish UX, remove dead project pages
Backend:
- Guard output callback and cleanup timer with try-catch
- Add zombie stream reaper (5min interval) with proper cleanup
- Force-flush assistant buffer at 50 segments to prevent unbounded growth
- Log warning on message buffer overflow
- Emit SSE warning when user message persistence fails
Frontend:
- Show spinner on send button while processing
- Add native tooltip on truncated conversation titles
- Make sidebar resize handle visible with subtle background
Dead code:
- Delete orphaned ProjectDetail, ProjectsList, ProjectsPage
- Remove /projects/:id route from App.tsx
* Dashboard landing page, chat empty state, API error quality, SQLite indexes
- Replace DashboardPage redirect with landing page showing recent
conversations and workflow runs in a two-column grid
- Fix /chat empty state to render ChatInterface in new-chat mode
instead of a static placeholder
- Add proper HTTP status codes to API: 404 for missing conversations,
400 for invalid codebase IDs, empty array for failed workflow discovery
- Add 3 missing indexes to SQLite schema from PG migrations 009/010
(workflow run staleness, session parent, session conversation lookup)
* Scope workflow runs to selected project
Pass the selected project's codebaseId when creating a conversation
for workflow execution. Show which project the workflow will target,
and disable the run controls when no project is selected.
* Inline project selector in workflow invocation panel
Replace static "Running on {project}" text with a <select> dropdown
so users can pick a project without leaving the workflow view.
* Fix chat header showing "No project" and new chat missing project
Header now resolves project name from codebase_id when cwd is absent.
Dashboard "New Chat" creates conversation with selected project instead
of navigating to an orphaned /chat route. Buttons disabled when no
project is selected.
* Sidebar nav, workflow builder route, workflow invoker in project detail
Add Workflows and Workflow Builder nav links to sidebar, extract
navLinkClass helper. Wire WorkflowInvoker into ProjectDetail. Add
WorkflowBuilderPage route. Remove dead redirect routes and unused
Header from pages that don't need it.
* Fix review issues: guard rm-rf, error handling, Error Boundary, dedup utility
- Guard DELETE /api/codebases/:id to only rm-rf paths under ~/.archon/workspaces/
(externally registered repos only get DB record deleted)
- Remove accidental e2e-testing-findings-session2.md
- Replace 3x .catch(() => undefined) with proper error logging
- Add React Error Boundary at app root to prevent white-screen crashes
- Wrap JSON.parse(metadata) in try-catch in ChatInterface and WorkflowLogs
- Upgrade SSE write failure logging from debug to warn, add missing logging
- Fix bare catch in SSE heartbeat to only swallow disconnect errors
- Remove unused _createErrorHandler parameter from registerApiRoutes
- Extract shared findMarkdownFilesRecursive to packages/core/src/utils/commands.ts
- Convert boolean to integer explicitly for SQLite hidden column
- Surface workflow discovery errors as warning in API response
* Address PR review: error handling, SSE resilience, test coverage
- Fix path traversal in codebase deletion (use normalizedCwd)
- Buffer SSE write failures for reconnect delivery (3 catch blocks)
- Extract flushBufferedMessages helper with partial-failure recovery
- Add defensive outer catch to background workflow dispatch
- Surface API/load errors to users (history, metadata, React Query)
- Add SSE parse validation and handler error surfacing
- Show stale indicator when workflow polling loses connection
- Add delete error handling to ConversationItem dialog
- Import shared types from @archon/core instead of duplicating
- Lower activity update failure threshold from 5 to 3
- Add test coverage for messages.ts and workflow-events.ts (100%)
* docs: Update documentation for Web UI, workflow events, and message persistence
- Update database schema description (workflow_events detail, messages metadata)
- Add Web UI platform adapter to architecture docs
- Document REST API endpoints for Web UI
- Add SSE streaming pattern documentation
- Update conversation schema (title, deleted_at columns)
- Expand Web UI feature list (workflow invocation, message persistence)
* Address PR review: error handling, type safety, SSE resilience
- Add null check on createWorkflowRun INSERT return
- Narrow catch in registerRepoAtPath to not swallow command loading errors
- Add SSE onerror logging and user notification on permanent close
- Add WarningEvent to SSE union and surface warnings in ChatInterface
- Fix WorkflowEventRow.data SQLite type mismatch (parse JSON string)
- Separate conversation lookup from auto-titling error handling
- Fix log levels for data loss scenarios (warn/debug → error)
- Emit SSE warning to user on flushAssistantMessage failure
- Set workflow run parent link regardless of success/failure
- Cap total buffered conversations at 200
- Define ArtifactType once in core, use everywhere
- Use imported status types in SSE event interfaces
- Add exhaustiveness checks in switch statements
- Preserve original git error in registerRepository
- Remove unused recoverable field from ErrorEvent
---------
Co-authored-by: Rasmus Widing <rasmus.widing@gmail.com>
* Investigate issue #315: hot reload ENOENT
* Fix: Hot reload fails with ENOENT (#315)
Root dev workflow used bun --cwd packages/server --watch src/index.ts, so Bun restarts could not resolve the relative packages/server path and crashed with ENOENT.
Changes:
- Replace the root dev script with bun --filter @archon/server dev so Bun runs the workspace script inside the package
- Align the root start script with the same workspace delegation to avoid future cwd issues
- Manually validated bun run dev hot reload and bun run start
Fixes#315
* Archive investigation for issue #315
* fix: Address review findings (CRITICAL/HIGH)
Fixes applied:
- add server smoke-test mode and integration coverage for bun run dev
- refresh issue-315 artifacts (root cause + history) and validation checklist
- correct port-allocation test expectations, update metadata and review artifacts
Tests added:
- packages/server/src/dev-script.smoke.test.ts
Skipped (see review artifacts):
- none
Review artifacts: .archon/artifacts/reviews/pr-320/
* refactor: Remove unnecessary smoke test infrastructure
The smoke test added ~160 lines of code to test a 2-line fix.
The fix (using --filter instead of --cwd) is simple and any
regression would be immediately obvious during development.
Removed:
- dev-script.smoke.test.ts (140 lines)
- Smoke test mode in index.ts (20 lines)
* docs: Add Phase 5 CLI binary distribution plan
- Create detailed implementation plan for binary distribution
- Add Phase 5.0: Bundle defaults for binary (depends on #322)
- Add Phase 5.1-5.7: Build scripts, GitHub Actions, curl install,
Homebrew formula, Windows docs, version command, release guide
- Update research doc with Phase 6 (auto-update command)
- Renumber dashboard to Phase 7, workflow builder to Phase 8
- Mark Phases 1-4 as complete in research doc
* feat: Phase 5 - CLI binary distribution
Implement standalone binary distribution for Archon CLI:
- Bundle default commands and workflows into binaries at compile time
- Add build scripts for cross-platform compilation (macOS/Linux, ARM64/x64)
- Create GitHub Actions release workflow triggered on version tags
- Add curl install script with checksum verification
- Create Homebrew formula for macOS/Linux installation
- Update version command to show platform, build type, and database info
- Add developer release guide documentation
- Update README with CLI installation instructions
Binary compilation uses Bun's --compile flag to create standalone
executables that include the Bun runtime and all dependencies.
Default workflows and commands are imported as text at compile time
and embedded directly into the binary.
* fix: Pin Dockerfile to Bun 1.3.4 to match lockfile version
The Docker build was failing because oven/bun:1-slim resolved to 1.3.6
while the lockfile was created with 1.3.4, causing --frozen-lockfile to fail.
* docs: Clarify binary vs source builds for default commands/workflows
* fix: Address PR review issues for CLI binary distribution
Security fixes:
- install.sh: Require SKIP_CHECKSUM=true to bypass checksum verification
instead of silently skipping (addresses security vulnerability)
- install.sh: Show actual error output when version check fails instead
of falsely reporting success
Validation improvements:
- checksums.sh: Validate all 4 expected binaries exist before generating
checksums to prevent releasing incomplete builds
- build-binaries.sh: Verify binary exists and has reasonable size (>1MB)
after each build step
- update-homebrew.sh: Validate extracted checksums are non-empty and
look like valid SHA256 hashes (64 hex chars)
- update-homebrew.sh: Fix sed patterns to use URL context for updating
checksums on subsequent runs
Bug fixes:
- homebrew/archon.rb: Fix test to expect exit code 0 (success) instead
of 1 for `archon version`
- loader.ts: Log error when bundled workflow fails to parse (indicates
build-time corruption)
Test coverage:
- Add bundled-defaults.test.ts for isBinaryBuild() and content validation
- Add connection.test.ts for getDatabaseType() function
- Add binary build bundled workflow tests to loader.test.ts
- Add binary build bundled command tests to executor.test.ts
All 959 tests pass.
* feat: Enforce ESLint zero-warnings policy in CI
- Update ESLint config to turn off false-positive rules (restrict-template-expressions,
no-unnecessary-condition, prefer-nullish-coalescing) and keep no-non-null-assertion as error
- Fix all 11 no-non-null-assertion errors in loader.ts, executor.ts, and command-handler.ts
- Add --max-warnings 0 to CI lint step and format:check step
- Update lint-staged to run ESLint with --fix on staged .ts files
- Update validate script to run type-check, lint --max-warnings 0, and format:check
- Document ESLint guidelines and pre-PR validation in CLAUDE.md
* test: Add file with lint error to verify CI failure
* Revert "test: Add file with lint error to verify CI failure"
This reverts commit f29d582cca24dedb51113202c8aed5cd5f6d0c9b.
* fix: Address PR review feedback for ESLint zero-warnings policy
- Restore tests to validate script (was accidentally removed)
- Update CLAUDE.md: fix "0 errors" → "0 warnings" terminology
- Update CLAUDE.md: replace eslint-disable example with guard clause pattern
- Update CLAUDE.md: expand disabled rules list with categories
- Organize eslint.config.mjs disabled rules by category with rationales
- Fix loader.ts error message to be more accurate about step validation
- Fix executor.ts comment to clarify the guard is meaningful (not just for TS)
* feat: Add workspace root configuration for Bun monorepo
Configure the root package.json, tsconfig.json, and eslint.config.mjs
for a Bun workspaces monorepo structure with packages/* workspace pattern.
- Convert root package.json to workspace root with workspaces: ["packages/*"]
- Update scripts to use bun --filter for cross-package commands
- Update tsconfig.json to serve as base config for packages to extend
- Update eslint.config.mjs for monorepo paths (packages/*/src/**)
- Update .gitignore for packages/*/node_modules and dist directories
* feat: Create @archon/core package with shared business logic
Extract all shared business logic into @archon/core package:
- types/ - Core TypeScript interfaces (IPlatformAdapter, IAssistantClient, etc.)
- utils/ - Shared utilities (git, auth, formatting, paths, etc.)
- config/ - YAML config loading (loadConfig, loadGlobalConfig, loadRepoConfig)
- state/ - Session state machine (TransitionTrigger, session transitions)
- db/ - PostgreSQL operations (conversations, codebases, sessions, etc.)
- clients/ - AI SDK wrappers (ClaudeClient, CodexClient, factory)
- isolation/ - Git worktree management (WorktreeProvider)
- workflows/ - YAML workflow engine (loader, executor, router, logger)
- services/ - Background services (cleanup-service)
- orchestrator/ - Message orchestration (handleMessage)
- handlers/ - Slash command processing (handleCommand, parseCommand)
- test/ - Test mocks and setup utilities
Package exports are organized with submodule paths for tree-shaking:
- @archon/core - Main exports
- @archon/core/db/* - Database operations
- @archon/core/utils/* - Utility functions
- @archon/core/workflows - Workflow types and functions
All 924 tests pass with the new structure.
* feat: Create @archon/server package with platform adapters
Extract platform-specific code into @archon/server package:
- adapters/ - Platform integrations (Telegram, Slack, Discord, GitHub, Test)
- index.ts - Express server entry point with health checks and webhook handlers
- scripts/ - Setup utilities (setup-auth.ts)
The server package depends on @archon/core via workspace:* reference
and imports shared business logic using @archon/core package paths.
Imports updated to use @archon/core:
- Types: import type { IPlatformAdapter } from '@archon/core'
- DB: import * as conversationDb from '@archon/core/db/conversations'
- Utils: import { handleMessage, ConversationLockManager } from '@archon/core'
Added .env symlink to packages/server/.env for dotenv compatibility.
* chore: Update bun.lock for workspace dependencies
Regenerated lockfile after restructuring to Bun workspaces with
@archon/core and @archon/server packages.
* docs: Update documentation for monorepo structure
Update CLAUDE.md, docs/architecture.md, and docs/new-developer-guide.md to reflect the new Bun monorepo structure introduced in PR #311.
Changes:
- Updated directory structure to show packages/core and packages/server
- Added import patterns section showing @archon/core and @archon/server usage
- Updated all file path references from src/* to packages/*/src/*
- Updated test command examples
- Clarified package split (core: business logic, server: adapters + HTTP)
* fix: Address PR review feedback - imports and auth naming
CLAUDE.md:
- Add typed imports guidance (always use `import type` for types,
specific named imports for values, avoid generic `import *`)
packages/core/src/index.ts:
- Alias all auth parseAllowedUserIds functions with platform prefix:
- parseTelegramAllowedUserIds (returns number[])
- parseSlackAllowedUserIds (returns string[])
- parseDiscordAllowedUserIds (returns string[])
- parseGitHubAllowedUsers (already aliased)
- Alias isUserAuthorized as isTelegramUserAuthorized for consistency
- Update JSDoc to mention isolation is extensible for containers/VMs
packages/core/src/db/index.ts:
- Update JSDoc to not overstate naming conflicts (db modules have
distinct function names)
packages/core/src/clients/index.ts:
- Clarify when to use submodule path vs main package
packages/server/src/adapters/telegram.ts:
- Update to use new aliased auth function names
* fix: Update CI and bunfig.toml for monorepo structure
- Update bunfig.toml test root from ./src to ./packages
- Update preload path to packages/core/src/test/setup.ts
- Update CI workflow test paths for packages/core and packages/server
* fix: Run factory tests in isolation to avoid mock.module pollution
Bun's mock.module() pollutes the global module registry, causing factory tests
to fail when run after claude.test.ts or codex.test.ts (which mock the clients).
Test execution order now:
1. Factory tests first (before any mock.module calls)
2. Client tests (claude, codex) that use mock.module
3. All other tests (db, utils, handlers, etc.)
4. Orchestrator tests last (also uses mock.module)
* fix: Run command-handler tests in isolation to avoid mock pollution
The command-handler tests use mock.module() for database mocks, which causes
test isolation issues when run in the same Bun process as other tests.
Test execution order now:
1. Factory tests (no mocks)
2. Client tests (claude, codex) with mock.module
3. Command-handler tests with mock.module (isolated from step 2)
4. All other tests (db, utils, config, etc.)
5. Orchestrator tests last (also uses mock.module)
* fix: Remove Claude credentials from .env.example
Claude Code uses global auth from `claude /login`, not project .env
files. Having tokens in .env.example caused Bun to auto-load them
in worktrees, overriding valid user credentials and causing auth failures.
- Comment out CLAUDE_CODE_OAUTH_TOKEN placeholder
- Comment out CLAUDE_API_KEY placeholder
- Add note explaining why these should not be set
* fix: Add CLAUDE_USE_GLOBAL_AUTH for SDK built-in authentication
Bun auto-loads .env files from the working directory, which caused
issues when worktrees contained CLAUDE_CODE_OAUTH_TOKEN - the invalid
token would override the user's valid global auth from `claude /login`.
Changes:
- Add CLAUDE_USE_GLOBAL_AUTH=true option to bypass credential check
- Update .env.example to use global auth by default (recommended)
- Remove explicit Claude tokens from .env.example template
This allows the Claude Code SDK to use its built-in OAuth authentication
instead of requiring explicit tokens in environment variables.
For Docker/VPS deployments, users can still set CLAUDE_CODE_OAUTH_TOKEN
or ANTHROPIC_API_KEY explicitly via environment variables at runtime.
Related: #227
* chore: Upgrade Claude Agent SDK to 0.2.7
Fixes hanging issue when running Claude Code in worktrees with
settingSources: ["project"]. The previous version (0.1.57/0.1.69)
would hang indefinitely when loading project settings.
* docs: Add CLAUDE_USE_GLOBAL_AUTH to documentation
Update CLAUDE.md and README.md to document the new recommended
authentication method using global auth from `claude /login`.
- CLAUDE.md: Updated Environment Variables section
- README.md: Restructured Claude Code section with 3 options
This addresses the documentation gaps identified in PR review.
* Investigate issue #226: Add pre-commit hook to prevent formatting drift
Analysis of the formatting drift issue that caused 12 files to fail
format:check during E2E validation. Root cause identified as missing
automated formatting enforcement in git workflow.
Proposed solution: husky + lint-staged to run Prettier on staged files
before each commit. Implementation plan documents all required changes
to package.json and new config files.
* chore: Add pre-commit hook to prevent formatting drift (#226)
Files were committed without running Prettier, causing format:check failures
during E2E validation. This adds automated formatting enforcement.
Changes:
- Add husky and lint-staged as devDependencies
- Add prepare script to initialize husky on install
- Create .lintstagedrc.json to format staged ts/js/json/md files
- Create .husky/pre-commit to run lint-staged before commits
Fixes#226
* chore: Add execute permission to pre-commit hook
* chore: Archive investigation for issue #226
- Replace yaml npm package with Bun.YAML.parse()
- Auto-create ~/.archon/config.yaml on first run with documented defaults
- Update validation script to check for config file existence
* Add Archon distribution config and directory structure
- Create centralized path resolution in src/utils/archon-paths.ts
- Add YAML configuration system (src/config/) with layered loading
- Update Dockerfile and docker-compose for /.archon/ directory
- Add GHCR publish workflow for multi-arch Docker builds
- Create deploy/ directory with end-user docker-compose
- Add /init command to create .archon structure in repos
- Add docs/configuration.md reference guide
- Update README with Quick Start section
- Add bun run validate script
- Update tests for new path defaults (~/.archon/)
Directory structure:
- Local: ~/.archon/{workspaces,worktrees,config.yaml}
- Docker: /.archon/{workspaces,worktrees}
- Repo: .archon/{commands,workflows,config.yaml}
Legacy WORKSPACE_PATH and WORKTREE_BASE env vars still supported.
* Complete Archon distribution config implementation
- Wire up config system in src/index.ts (Task 3.5)
- Remove legacy WORKSPACE_PATH and WORKTREE_BASE support
- Add logConfig() function to config-loader.ts
- Update docker-compose.yml to use ARCHON_DOCKER env var
- Remove legacy env vars from .env.example
- Update all documentation to reference ARCHON_HOME
- Create scripts/validate-setup.sh for setup validation
- Add setup:check script to package.json
- Create docs/getting-started.md guide
- Create docs/archon-architecture.md technical docs
- Update tests to use ARCHON_HOME instead of legacy vars
- Fix validate.md command template for new paths
All plan phases now complete:
- Phase 1: Archon Directory Structure
- Phase 2: Docker Distribution
- Phase 3: YAML Configuration System
- Phase 4: Developer Experience
- Phase 5: Documentation
* Migrate from Node.js/npm/Jest to Bun runtime
- Replace npm with bun for package management (bun.lock)
- Replace Jest with bun:test for testing
- Update tsconfig for Bun (ESNext module, bundler resolution)
- Update Dockerfile to use oven/bun:1-slim
- Update CI workflow to use oven-sh/setup-bun@v2
- Remove dynamic import hack from codex.ts (direct ESM imports)
- Fix test mocking for Bun (export execFileAsync, use spyOn)
- Update all documentation (CLAUDE.md, README.md, CONTRIBUTING.md)
All 395 tests pass, type-check passes, E2E validated with curl.
* ci: retrigger CI build
* fix: make execFileAsync a function for better Bun mockability
* fix: ensure execFileAsync returns string not Buffer
* fix: rename _execFileAsync to comply with naming convention
* fix: make mkdirAsync mockable for Bun tests
* fix: update engines to bun>=1.0.0 and add mkdirAsync mock
* fix: pin Bun to 1.3.4 in CI to fix mock.module test failures
Newer Bun versions have different mock.module() behavior that causes
cross-test module pollution, resulting in 71 test failures in CI while
tests pass locally. Pinning to 1.3.4 ensures consistent behavior.
* fix: run orchestrator tests last to avoid mock.module pollution
Bun's mock.module() pollutes the global module cache, causing tests to
fail when orchestrator.test.ts (which mocks command-handler and factory)
runs before those modules' own test files.
Fix by running tests in two batches:
1. All tests except orchestrator
2. Orchestrator tests last
This ensures orchestrator's mocks don't affect other test files.
- Add SlackAdapter using @slack/bolt with Socket Mode (no HTTP endpoints needed)
- Implement thread handling mirroring Discord pattern (channel:thread_ts conversation IDs)
- Add Slack URL normalization to strip <url> formatting from messages
- Add user whitelist authorization (SLACK_ALLOWED_USER_IDS)
- Support @mention activation in channels and direct DMs
- Add comprehensive setup guide and update README with Slack section
* Fix npm deprecation warnings and vulnerability
- Update Jest 29→30.2.0 to eliminate glob@7/inflight deprecation warnings
- Update Express 5.1.0→5.2.1 to fix query property vulnerability
- Update ts-jest 29.1.0→29.4.6 for Jest 30 compatibility
- Update @types/jest 29.5.0→30.0.0 for Jest 30 types
- Add npm override for test-exclude@7 to fully eliminate glob@7
* Update SDK and tooling dependencies to latest
- Implement DiscordAdapter using discord.js v14 with IPlatformAdapter interface
- Support 2000 char message limit with automatic splitting
- Add MESSAGE_CONTENT intent for reading messages
- Fix dotenv import order to use 'dotenv/config' for proper env loading
- Update batch mode tests to account for "starting" message
Co-Authored-By: Claude <noreply@anthropic.com>
* feat: Add Telegram MarkdownV2 formatting for AI responses
- Add telegramify-markdown package to convert GitHub-flavored markdown
to Telegram's MarkdownV2 format
- Create telegram-markdown utility with:
- convertToTelegramMarkdown(): Main conversion function
- stripMarkdown(): Fallback for plain text
- escapeMarkdownV2(): Manual escaping helper
- Update TelegramAdapter to:
- Format short messages with MarkdownV2
- Split long messages by paragraphs for better formatting
- Fallback to stripped plain text when MarkdownV2 parsing fails
- Add comprehensive tests for markdown conversion
Transforms AI responses from raw markdown (## headers, **bold**) to
properly formatted Telegram messages with bold text, code blocks, etc.
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: Correct telegram adapter test mocks and assertions
- Add missing stripMarkdown mock to telegram-markdown module mock
- Fix paragraph splitting test to use double newlines (\n\n) matching
actual implementation behavior
- Use smaller paragraph sizes (3000 chars) to stay within MAX_LENGTH
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* docs: add PRP for improving test coverage
- Create comprehensive PRP documenting test infrastructure improvements
- Add coverage directory to .gitignore
- Plan covers 6 phases: infrastructure, utilities, database, adapters, orchestrator, CI/CD
- Target: increase coverage from 15.98% to 80%+
* test: add comprehensive unit test coverage
- Add test infrastructure: setup.ts, mock utilities for database, platform, and streaming
- Add tests for all database modules (conversations, codebases, sessions)
- Add tests for test adapter, client factory, orchestrator
- Expand Claude and Codex client tests with full mock coverage
- Add tool-formatter tests
- Configure Jest with coverage thresholds (30% branches, 40% functions/lines/statements)
- Add CI workflow for automated testing on push/PR
- Add test:coverage and test:ci npm scripts
Coverage: 170 tests passing, 53% lines, 48% branches, 65% functions
Co-Authored-By: Claude <noreply@anthropic.com>
* chore: improve test coverage and fix type issues
- Fix type annotations across multiple files
- Improve test mocks for streaming and database operations
- Update jest config for better coverage reporting
- Fix minor type issues in orchestrator, sessions, and adapters
- Update documentation for architecture and cloud deployment
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>