- Fix double bold markers (****) when heading text already contains **
- Strip markdown formatting (**bold**, *italic*, ~~strike~~) from table cells
since Feishu table elements do not support markdown rendering
Fixes rendering issues where:
1. Headings like '**text**' were rendered as '****text****'
2. Table cells with '**bold**' showed raw markdown instead of plain text
Remove the in-progress reaction (reactEmoji) and optionally add a
done reaction (doneEmoji) when the final response is sent, so users
get visual feedback that processing has finished.
Signed-off-by: Sihyeon Jang <sihyeon.jang@navercorp.com>
Replace manual _active_spinner + _pause_spinner/_resume_spinner with
_ThinkingSpinner class that owns the spinner lifecycle via __enter__/
__exit__ and provides a pause() context manager for temporarily
stopping the spinner during progress output.
Benefits:
- Restores Pythonic context manager pattern matching original code
- Eliminates duplicated start/stop boilerplate between single-message
and interactive modes
- pause() context manager guarantees resume even if print raises
- _active flag prevents post-teardown resume from async callbacks
The Rich console.status() spinner ('nanobot is thinking...') was not
cleared when tool call progress lines were printed during processing,
causing overlapping/garbled terminal output.
Replace the context-manager approach with explicit start/stop lifecycle:
- _pause_spinner() stops the spinner before any progress line is printed
- _resume_spinner() restarts it after printing
- Applied to both single-message mode (_cli_progress) and interactive
mode (_consume_outbound)
Closes#1956
Replace fire-and-forget consolidation with archive_messages(), which
retries until the raw-dump fallback triggers — making it effectively
infallible. /new now clears the session immediately and archives in
the background. Pending archive tasks are drained on shutdown via
close_mcp() so no data is lost on process exit.
PR #881 (commit 755e424) fixed the race condition between normal consolidation
and /new consolidation, but did so by making /new wait for consolidation to
complete before returning. This hurts user experience - /new should be instant.
This PR restores the original immediate-return behavior while keeping safety:
1. **Immediate return**: Session clears and user sees "New session started" right away
2. **Background archival**: Consolidation runs in background via asyncio.create_task
3. **Serialized consolidation**: Uses the same lock as normal consolidation via
`memory_consolidator.get_lock()` to prevent concurrent writes
If consolidation fails after session clear, archived messages may be lost.
This is acceptable because:
- User already sees the new session and can continue working
- Failure is logged for debugging
- The alternative (blocking /new on every call) hurts UX for all users
- Add CONTRIBUTING.md with detailed contribution guidelines
- Add branching strategy section to README.md explaining main/nightly branches
- Include maintainer information and development setup instructions
Phase 1 _decide() now includes "Current date/time: YYYY-MM-DD HH:MM UTC"
in the user prompt and instructs the LLM to use it for time-aware scheduling.
Without this, the LLM defaults to 'run' for any task description regardless
of whether it is actually due, defeating Phase 1's pre-screening purpose.
Closes#1929