Skip to content

feat: add typing-time autosuggest to slash commands - #38

Merged
chauncygu merged 3 commits into
SAIL-Research-Lab:mainfrom
honghua:typing-autosuggest-v1
Apr 15, 2026
Merged

feat: add typing-time autosuggest to slash commands#38
chauncygu merged 3 commits into
SAIL-Research-Lab:mainfrom
honghua:typing-autosuggest-v1

Conversation

@honghua

@honghua honghua commented Apr 15, 2026

Copy link
Copy Markdown

Replace the Tab-only readline completer with a prompt_toolkit PromptSession that renders an inline ghost suggestion while typing and a keyboard-selectable completion menu.
Fixes three user-visible defects in the REPL:

1. No as-you-type suggestion — completion only fired on Tab.
2. The popped-up match list was not selectable (no menu-complete binding, no arrow-key handling; the display hook was pure stdout.write).
3. Typing `/c` followed by more input dispatched as `/c/cwd` → "Unknown command", because `/` had been removed from readline's word delimiters and `handle_slash` splits only on whitespace.

Also surfaces modular/plugin/skill commands in completion for the first time. The previous completer read only the hand-maintained _CMD_META dict, while the dispatcher consulted the full live COMMANDS registry.

@chauncygu

Copy link
Copy Markdown
Contributor

Thanks for the detailed PR! The autosuggest feature is a nice idea, but there are several issues that prevent merging as-is:

  1. Hard dependency vs. fallback contradiction
    prompt_toolkit is added to dependencies (required), but ui/input.py has a HAS_PROMPT_TOOLKIT = False fallback path. Pick one — if it's required, the fallback is dead code; if it's optional,
    move it to [project.optional-dependencies].

  2. History file format conflict
    readline and prompt_toolkit's FileHistory use different formats. Sharing the same HISTORY_FILE between them risks corrupting history, especially on fallback from prompt_toolkit to readline
    mid-session.

  3. Circular import risk
    ui/input.py → import cheetahclaws → import ui.input creates a circular dependency. The lazy import mitigates it today, but it's fragile.

  4. Multi-line paste behavior change
    The current _read_input has careful bracketed-paste handling (Phase 2/3) with a "pasted N lines" message. The prompt_toolkit path bypasses all of this, changing user-visible behavior
    silently.

  5. Bug fix mixed with feature
    The readline /c/cwd glue fix and the prompt_toolkit feature should be separate PRs. We've already fixed the readline bug on main (changed "/" in line → line.startswith("/")).

If you'd like to revisit this, I'd suggest:

  • Make prompt_toolkit an optional dependency
  • Use a separate history file for prompt_toolkit
  • Resolve the circular import (e.g. pass COMMANDS/META via setup() instead of importing cheetahclaws)
  • Split the readline fix into its own PR

Thanks again for the contribution!

honghua pushed a commit to honghua/cheetahclaws that referenced this pull request Apr 15, 2026
…ar import

Addresses all five points raised in PR SAIL-Research-Lab#38 review:

1. Hard dep vs fallback contradiction — move prompt_toolkit out of
   [project.dependencies] into [project.optional-dependencies] under a new
   `autosuggest` extra. requirements.txt marks it optional with a comment.
   The HAS_PROMPT_TOOLKIT=False fallback is now a genuine supported path.

2. History file format conflict — introduce a sibling history file for
   prompt_toolkit (input_history_pt.txt) derived via HISTORY_FILE.with_name(),
   leaving the readline HISTORY_FILE untouched. Toggling CHEETAH_PT_INPUT no
   longer risks corrupting either file.

3. Circular import risk — ui/input.py no longer imports cheetahclaws.
   Providers are injected via ui.input.setup(commands_provider, meta_provider)
   from repl(); SlashCompleter reads module-level providers (or ctor overrides
   for tests). Added test_module_does_not_import_cheetahclaws as a structural
   regression guard.

4. Multi-line paste notification parity — after _pt_read_line returns,
   _read_input counts embedded \\n and emits the same info("(pasted N lines)")
   message as the readline phase-2 path, preserving user-visible behavior.

5. Bug fix mixed with feature — setup_readline reverted to its pre-patch
   state. The /c/cwd readline glue fix now lives entirely on main; this PR
   only adds the prompt_toolkit input path.

Folded in self-review items: reset_session() helper to drop a stale cached
session after a prompt_toolkit failure; richer exception context in the
fallback warn; session cache now invalidates on history_path change;
completer cache keyed on full sorted tuple of command names.

Tests: 14 autocomplete tests pass (9 unit + 3 PTY + 2 new regression guards
for setup injection and no-circular-import); full suite 306 passing
(test_voice and test_diff_view excluded — pre-existing, unrelated).
@honghua
honghua force-pushed the typing-autosuggest-v1 branch from 1d8b463 to 4f3305e Compare April 15, 2026 03:11
@honghua

honghua commented Apr 15, 2026

Copy link
Copy Markdown
Author

Thanks for the careful review — all five points addressed in the latest push.

@chauncygu

Copy link
Copy Markdown
Contributor

Thanks for the thorough rework.

The PR looks good to merge, but main has changed significantly since your branch was created (module reorganization, config/runtime separation, new setup wizard, etc.), so there will be merge conflicts in cheetahclaws.py, pyproject.toml, and requirements.txt.

image

Could you rebase onto the latest main and resolve the conflicts? The changes are mostly mechanical — the key things to watch for:

  • tools.py is now tools/init.py
  • mcp/ is now cc_mcp/
  • requirements.txt has been rewritten (core deps only, optional deps commented out)
  • The REPL prompt now includes a context usage percentage indicator

Once rebased, I'll merge it.

Thanks a lot for your great contributions!

Harry Yang added 2 commits April 14, 2026 21:09
Replace the Tab-only readline completer with a prompt_toolkit
PromptSession that renders an inline ghost suggestion while typing
and a keyboard-selectable completion menu.
Fixes three user-visible defects in the REPL:

    1. No as-you-type suggestion — completion only fired on Tab.
    2. The popped-up match list was not selectable (no menu-complete
binding, no arrow-key handling; the display hook was pure stdout.write).
    3. Typing `/c` followed by more input dispatched as `/c/cwd` →
       "Unknown command", because `/` had been removed from readline's
word delimiters and `handle_slash` splits only on whitespace.

Also surfaces modular/plugin/skill commands in completion for the first time.
The previous completer read only the hand-maintained `_CMD_META` dict,
while the dispatcher consulted the full live `COMMANDS` registry.
…ar import

Addresses all five points raised in PR SAIL-Research-Lab#38 review:

1. Hard dep vs fallback contradiction — move prompt_toolkit out of
   [project.dependencies] into [project.optional-dependencies] under a new
   `autosuggest` extra. requirements.txt marks it optional with a comment.
   The HAS_PROMPT_TOOLKIT=False fallback is now a genuine supported path.

2. History file format conflict — introduce a sibling history file for
   prompt_toolkit (input_history_pt.txt) derived via HISTORY_FILE.with_name(),
   leaving the readline HISTORY_FILE untouched. Toggling CHEETAH_PT_INPUT no
   longer risks corrupting either file.

3. Circular import risk — ui/input.py no longer imports cheetahclaws.
   Providers are injected via ui.input.setup(commands_provider, meta_provider)
   from repl(); SlashCompleter reads module-level providers (or ctor overrides
   for tests). Added test_module_does_not_import_cheetahclaws as a structural
   regression guard.

4. Multi-line paste notification parity — after _pt_read_line returns,
   _read_input counts embedded \\n and emits the same info("(pasted N lines)")
   message as the readline phase-2 path, preserving user-visible behavior.

5. Bug fix mixed with feature — setup_readline reverted to its pre-patch
   state. The /c/cwd readline glue fix now lives entirely on main; this PR
   only adds the prompt_toolkit input path.

Folded in self-review items: reset_session() helper to drop a stale cached
session after a prompt_toolkit failure; richer exception context in the
fallback warn; session cache now invalidates on history_path change;
completer cache keyed on full sorted tuple of command names.

Tests: 14 autocomplete tests pass (9 unit + 3 PTY + 2 new regression guards
for setup injection and no-circular-import); full suite 306 passing
(test_voice and test_diff_view excluded — pre-existing, unrelated).
@honghua
honghua force-pushed the typing-autosuggest-v1 branch from 4f3305e to 59dc9f1 Compare April 15, 2026 04:14
…0-3.13 compat

`Path.read_text` gained a `newline=` parameter only in Python 3.14, but
this project supports 3.10+. Three call sites in tools/fs.py were passing
newline="" to read_text and failing at runtime on every supported version,
surfacing as `test_diff_view` CI failures.

Extracted a small `_read_preserving_newlines(p)` helper using `p.open(...,
newline="")` (accepted since pathlib's inception) and routed the three
callers through it. Same semantics — \\r\\n preserved so _edit's CRLF
detection still works — now portable across 3.10-3.14.

Unrelated to the autosuggest feature in this PR, but required to unblock
CI. Full suite: 341/341 pass.
@honghua

honghua commented Apr 15, 2026

Copy link
Copy Markdown
Author

Rebased onto v3.05.70 — no merge conflicts after the mcp/cc_mcp/ rename and module reorg landed cleanly.

Also included a small CI-unblocking compat fix for tools/fs.py: three Path.read_text(newline=...) call sites were failing on Python 3.10–3.13 (the newline= kwarg on read_text is 3.14+ only). Swapped to open(..., newline="") via a small helper — same semantics, portable across all supported Python versions.

Happy to pull that fix into a separate PR if you'd prefer; it's a standalone 1-file, +14/-5 change. Full suite: 341/341 pass locally.

Ready for merge whenever you have a moment.

@chauncygu
chauncygu merged commit b7318f4 into SAIL-Research-Lab:main Apr 15, 2026
@chauncygu

Copy link
Copy Markdown
Contributor

Thanks a lot!

Already merged.

mesler1 pushed a commit to mesler1/GAAT that referenced this pull request Apr 18, 2026
…ar import

Addresses all five points raised in PR SAIL-Research-Lab#38 review:

1. Hard dep vs fallback contradiction — move prompt_toolkit out of
   [project.dependencies] into [project.optional-dependencies] under a new
   `autosuggest` extra. requirements.txt marks it optional with a comment.
   The HAS_PROMPT_TOOLKIT=False fallback is now a genuine supported path.

2. History file format conflict — introduce a sibling history file for
   prompt_toolkit (input_history_pt.txt) derived via HISTORY_FILE.with_name(),
   leaving the readline HISTORY_FILE untouched. Toggling CHEETAH_PT_INPUT no
   longer risks corrupting either file.

3. Circular import risk — ui/input.py no longer imports cheetahclaws.
   Providers are injected via ui.input.setup(commands_provider, meta_provider)
   from repl(); SlashCompleter reads module-level providers (or ctor overrides
   for tests). Added test_module_does_not_import_cheetahclaws as a structural
   regression guard.

4. Multi-line paste notification parity — after _pt_read_line returns,
   _read_input counts embedded \\n and emits the same info("(pasted N lines)")
   message as the readline phase-2 path, preserving user-visible behavior.

5. Bug fix mixed with feature — setup_readline reverted to its pre-patch
   state. The /c/cwd readline glue fix now lives entirely on main; this PR
   only adds the prompt_toolkit input path.

Folded in self-review items: reset_session() helper to drop a stale cached
session after a prompt_toolkit failure; richer exception context in the
fallback warn; session cache now invalidates on history_path change;
completer cache keyed on full sorted tuple of command names.

Tests: 14 autocomplete tests pass (9 unit + 3 PTY + 2 new regression guards
for setup injection and no-circular-import); full suite 306 passing
(test_voice and test_diff_view excluded — pre-existing, unrelated).
nekocheik pushed a commit to nekocheik/cheetahclaws-fork that referenced this pull request Apr 19, 2026
… deps

Pre-POC bundle wires Silverhawk fork MVP core into cheetahclaws runtime:

1. cheetahclaws.py: import bridges.matrix + tools.a2a_delegate,
   COMMANDS['matrix']=cmd_matrix, COMMAND_HELP entry
2. web/api.py: add bridges.matrix to bridge auto-discovery
3. pyproject.toml: silverhawk-matrix optional = matrix-nio>=0.24.0
4. bootstrap.py: step 2.b register_a2a_handler logging POC handler,
   non-fatal if bridge absent

Smoke PASS: COMMANDS wired, tools registered, bootstrap runs clean,
pip install -e '.[silverhawk-matrix]' installable.

MVP core pre-POC wiring complete. Ready SAIL-Research-Lab#38 E2E.

refs SAIL-Research-Lab#33 SAIL-Research-Lab#35 SAIL-Research-Lab#38
nekocheik pushed a commit to nekocheik/cheetahclaws-fork that referenced this pull request Apr 19, 2026
…-matrix-serve.py + launch runbook

Wire Path B option δ for POC SAIL-Research-Lab#38: cheetahclaws runs standalone Matrix
agent bypassing chat-server-bin.

Adds:
- CLAUDE.md at fork root: pilot role overlay (Cas A forward-verbatim +
  MXID roster + A2A rules) sourced from DevopMaster agent/roles/prompts/
  pilot.md. Cheetahclaws reads it as system context.
- scripts/silverhawk-matrix-serve.py: standalone launcher binding matrix
  bridge inbound queue → agent.run() → mx_send outbound reply. Bypasses
  chat-server-bin entirely. SIGTERM-safe, accept_all permissions for POC.
- docs-silverhawk/poc-38-launch-spec.md: runbook for devop-master (new
  Matrix token generation via Dendrite login, stop classic supervisor
  units, launch cheetahclaws standalone, smoke probe, observation setup,
  POC run plan, rollback).

Closes wiring gap flagged post-SAIL-Research-Lab#37 (cheetahclaws installed but not
active runtime). Enables true POC thesis validation.

refs SAIL-Research-Lab#33 SAIL-Research-Lab#34 SAIL-Research-Lab#35 SAIL-Research-Lab#37 SAIL-Research-Lab#38
nekocheik pushed a commit to nekocheik/cheetahclaws-fork that referenced this pull request Apr 19, 2026
…AIL-Research-Lab#56

Add scripts/silverhawk-launch.sh (bash wrapper):
- Sources /usr/local/bin/glm to export ANTHROPIC_AUTH_TOKEN + BASE_URL
  (z.ai gateway Anthropic-compat for glm-* models)
- Parses /home/ide/.config/matrix/credentials.json for MATRIX_*
- Uses pkill pattern for stop-start swap (supervisorctl broken in
  these containers per preflight audit SAIL-Research-Lab#56)
- Execs silverhawk-matrix-serve.py in foreground

Update runbook poc-38-launch-spec.md per preflight findings:
- No new Matrix token generation needed (reuse credentials.json +
  stop-start swap frees the @testbot session cleanly)
- pkill stop pattern (supervisord lacks [supervisorctl] section)
- Cred sourcing inline from /usr/local/bin/glm + credentials.json
- Simplified 6-step checklist (fork pull → matrix-nio install →
  creds confirm → stop classic via launcher → launch → smoke)
- Rollback procedure (pkill serve + nohup restart classic)

refs SAIL-Research-Lab#33 SAIL-Research-Lab#34 SAIL-Research-Lab#35 SAIL-Research-Lab#37 SAIL-Research-Lab#38 SAIL-Research-Lab#56
nekocheik pushed a commit to nekocheik/cheetahclaws-fork that referenced this pull request Apr 19, 2026
…m-5 prefix

Devop-master blocker SAIL-Research-Lab#1 (SAIL-Research-Lab#56 preflight): plain 'glm-5' routes via
cheetahclaws _PREFIXES auto-detect to zhipu provider (bigmodel.cn
native API) — wrong endpoint. Prod uses z.ai gateway Anthropic-compat
(ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic + same token pattern
as /usr/local/bin/glm wrapper).

Fix: explicit provider prefix 'anthropic/glm-5'. cheetahclaws'
detect_provider() returns 'anthropic' (via '/' split), bare_model()
strips to 'glm-5' before API call. anthropic SDK Anthropic() client
auto-reads ANTHROPIC_BASE_URL env var → routes to z.ai gateway.

No providers.py patch needed. 2 file changes:
- silverhawk-matrix-serve.py: CHEETAHCLAWS_MODEL default 'anthropic/glm-5'
- silverhawk-launch.sh: log message reflects provider routing

Verified: detect_provider('anthropic/glm-5') = 'anthropic',
bare_model = 'glm-5', Anthropic() SDK honors ANTHROPIC_BASE_URL env
(smoke test returns base_url=<env value>).

refs SAIL-Research-Lab#38 SAIL-Research-Lab#56
nekocheik pushed a commit to nekocheik/cheetahclaws-fork that referenced this pull request Apr 19, 2026
Devop-master live test caught history-replay spam: on bootstrap,
nio's initial sync returned full pending history for joined rooms,
triggering callback on past RoomMessageText events. Side-effect:
cheetahclaws auto-responded to stale A2A envelopes from earlier
orchestrator cycles (6 mx_send_ok events before kill).

Fix: prime client.next_batch via a single-shot sync(timeout=0) BEFORE
registering the event callback. Events in that initial sync are
discarded (callback not registered yet). sync_forever(since=...) then
only dispatches fresh events.

Safe for repeat boots: nio auto-reuses next_batch if store exists,
so returning clients pick up where they left off. First-time boot
skips history as intended.

refs SAIL-Research-Lab#33 SAIL-Research-Lab#38 SAIL-Research-Lab#56
nekocheik pushed a commit to nekocheik/cheetahclaws-fork that referenced this pull request Apr 19, 2026
…uest grant

Run 2 bot promised but never executed tools. Dual bug:

1. Config key typo: 'permissions_mode' → 'permission_mode' (singular,
   per agent.py:294). Value 'accept_all' → 'accept-all' (hyphen, per
   _check_permission line 301). Wrong keys fell through to 'auto'.

2. 'auto' yields PermissionRequest event per tool; our loop discarded
   it → req.granted default False → tool denied → LLM saw denial.

Fixes serve.py: correct config keys + consume PermissionRequest +
grant=True as defense belt. TurnDone now loop-marker not loop-end
(agent.run multi-turn for tool workflows).

refs SAIL-Research-Lab#38 SAIL-Research-Lab#60
nekocheik pushed a commit to nekocheik/cheetahclaws-fork that referenced this pull request Apr 19, 2026
…activation

POC SAIL-Research-Lab#38 L1 live test validated: model name choice gates z.ai tool_use
schema emission. Devop forensic:

- model=glm-5 → z.ai returns text-only, 0 tool_use blocks (in=36k out=33)
- model=claude-sonnet-4-6 → z.ai server-side maps to glm backing model
  AND activates tool_use. Bash/Read/Edit/etc. all work.

Changes:
- serve.py default CHEETAHCLAWS_MODEL → anthropic/claude-sonnet-4-6
- launcher log reflects new default + gotcha explanation
- CLAUDE.md adds model-name note for fleet operators

Keep anthropic/ prefix: prefix auto-detect would otherwise route plain
glm-5 to bigmodel.cn (wrong endpoint). Anthropic SDK auto-reads
ANTHROPIC_BASE_URL env → z.ai gateway.

refs SAIL-Research-Lab#38 SAIL-Research-Lab#60 SAIL-Research-Lab#61
nekocheik pushed a commit to nekocheik/cheetahclaws-fork that referenced this pull request Apr 19, 2026
… prose-prefixed bodies

POC SAIL-Research-Lab#38 L3 diagnosis (devop evidence): cheetahclaws-sending peer emits
prose+JSON single message ('Je vais contacter @Reviewer... {envelope}').
Classic bridge.py AND pre-fix matrix.py both reject with strict
lstrip().startswith('{"a2a":"1"') check.

Fix: _extract_a2a_envelope() tolerant scanner.
- Fast path preserves strict-JSON hot path (pure JSON body unchanged
  behavior)
- Tolerant path: content.find('{"a2a":"1"') + balanced-brace walker
  handling nested {}, strings with braces, escapes
- Returns parsed dict or None

Smoke 9/9 PASS:
- Pure JSON ✓
- Pure JSON leading whitespace ✓
- Prose prefix ✓ (pilot SAIL-Research-Lab#6 / L3 case)
- Prose prefix multi-line ✓
- Nested braces in payload ✓
- Strings containing braces ✓
- No envelope → None ✓
- Malformed JSON → None ✓
- Wrong version a2a:2 → None ✓

Critical pre-Step-I3 L3-repeat: ide-0081 recycle cheetahclaws-native
needs matching tolerant detection on both sides.

refs SAIL-Research-Lab#71 SAIL-Research-Lab#38
nekocheik pushed a commit to nekocheik/cheetahclaws-fork that referenced this pull request Apr 19, 2026
… filter

POC SAIL-Research-Lab#38 L3 Run 2 root causes identified:
- Both bots loaded CLAUDE.md (pilot role) → @Reviewer self-ID as pilot
- No fleet-peer filter → text echo loop testbot↔reviewer

Fixes:
1. ROLE SPLIT — serve.py _load_system_prompt: SILVERHAWK_ROLE env OR
   MATRIX_USER_ID localpart inference (@testbot→pilot, @Reviewer→
   reviewer) → roles/<role>.md. Same image, different per-role context.

2. FLEET-PEER FILTER — matrix.py drops prose-only messages from known
   fleet peers (SILVERHAWK_FLEET_PEERS env OR roster fallback).
   Envelopes always route. Operators always queue.

Added roles/pilot.md (239L) + roles/reviewer.md (230L) from canonical.

Smoke 4/4 PASS (peers default+env, role no-env/pilot/reviewer/architech).

refs SAIL-Research-Lab#73 SAIL-Research-Lab#38
nekocheik pushed a commit to nekocheik/cheetahclaws-fork that referenced this pull request Apr 19, 2026
…t emit

POC SAIL-Research-Lab#38 L3 unblocker: reviewer detected envelope but never emitted
ack/result (detect-only handler). Wire active-agent protocol.

matrix.py: register_a2a_handler sig extended (env, item) — item has
room_id/sender/event_id for ack/result routing.

serve.py: _make_a2a_handler factory with closure over config +
system_prompt. On delegate/query:
1. emit ack envelope immediately via mx.mx_send
2. build prompt = payload.task + payload.context
3. dispatch fresh AgentState + _run_one_turn (no contamination)
4. emit result envelope (status, summary cap 6000 chars)
5. non-actionable actions log only (result handled elsewhere)

main() wires handler overriding bootstrap detect-only (idempotent).

Smoke OK. Acceptance L3-repeat 6/6 GREEN post hot-patch.

refs SAIL-Research-Lab#75 SAIL-Research-Lab#38
nekocheik pushed a commit to nekocheik/cheetahclaws-fork that referenced this pull request Apr 19, 2026
… L3 final patterns

Append 10 entries post-POC SAIL-Research-Lab#38 L3 Final GREEN (corr=f90a6e5d) :

Handler wiring & L3 final (41-50):
- 41 detect-only handler != active handler (keystone L3 FINAL)
- 42 fresh AgentState for delegates = session isolation
- 43 immediate ack emit <1s pattern
- 44 TurnDone → symmetric result envelope swap
- 45 SILVERHAWK_FLEET_PEERS empty != opt-out caveat (config doc follow-up)
- 46 cheetahclaws-native end-to-end vs classic WS-delegated architecture
- 47 tolerant balanced-brace parser > regex (nested braces + strings)
- 48 role split SILVERHAWK_ROLE + MXID fallback = 1-to-1 identity
- 49 cross-instance A2A full cycle ~65s budget (Opus tier)
- 50 POC L1→L2→L3 canonical progression rule

Total 50 entries from session. Sign-off updated.

refs SAIL-Research-Lab#77
nekocheik pushed a commit to nekocheik/cheetahclaws-fork that referenced this pull request Apr 19, 2026
Architecture spec for polymarket bot team deploy post-POC SAIL-Research-Lab#38 ratif.
Spec-before-deploy pattern: architech specs, devop-master deploys.

8 sections:
1. Container strategy — 3 dedicated ide-0090/0091/0092 per strategy
2. Virtual wallet persistence — JSON file + hourly memory.save backup
3. Strategy execution loop — cheetahclaws REPL + cron-like polling
4. Polymarket API rate limits — shared 52/min budget across 3 strategies
5. Risk management — per-position caps + 20% HWM drawdown halt + blocklist
6. Deploy checklist for devop-master — 6-step container spawn + code deploy + launch + smoke
7. Open questions for user (inherited from 054182e research)
8. Success criteria POC polymarket — 7-day uptime + PnL baseline comparison

Ratification required: PO approval container strategy + user approval
virtual allocation + news API deferred + real-trading held.

refs SAIL-Research-Lab#69
nekocheik pushed a commit to nekocheik/cheetahclaws-fork that referenced this pull request Apr 19, 2026
Audit cheetahclaws cross-turn persistence post-BLUEFOX42 fail.

Current: main() single AgentState shared across _run_one_turn calls.
state.messages accumulated via agent.py:86+187. 3 hypotheses for
test fail: thread race, sanitize stripping, CLI-vs-Matrix path.

Options:
- A (native): per-room AgentState map, thread-safe lock, 40-60 LOC
  — RECOMMENDED (canonical, self-contained, aligns POC SAIL-Research-Lab#38 arch)
- B (shim): REST fetch chat.db history + prepend, 60-80 LOC —
  fallback if A reveals agent-loop gap

Plan: (1) re-test BLUEFOX42 via real Matrix DMs; (2) if fails ship A;
(3) gates baseline+scale+isolation.

refs SAIL-Research-Lab#76
nekocheik pushed a commit to nekocheik/cheetahclaws-fork that referenced this pull request Apr 19, 2026
…e refusal

User catch 2026-04-19 morning: delegate 'envoyer message user'
→ reviewer refused textually 'je ne peux pas envoyer Matrix DM'
instead of composing message as payload.summary.

Analog Pilot SAIL-Research-Lab#6 retract gap, reviewer-side this time. reviewer.md
only had Cas A (audit) canon, no user-message path.

Fix: explicit Cas A/B/C:
- A: audit/review → 🔴/🟡/🟢 buckets in summary
- B: user-facing message → THE message text, pilot forwards verbatim
- C: technical non-review → short direct answer

Anti-pattern Cas B = exact refusal text from L3 FINAL corr=f90a6e5d.
Global rule: never refuse by tool-use timidity.

Scope: +76 / -8 LOC, prompt-only.

refs SAIL-Research-Lab#79 SAIL-Research-Lab#38
nekocheik pushed a commit to nekocheik/cheetahclaws-fork that referenced this pull request Apr 19, 2026
User test corr=4bf697fe: testbot emitted delegate but reviewer never
received. Root cause: a2a_delegate.py passed target_mxid as room_id to
mx_send. Matrix room_id starts '!' not '@' — nio silent-rejects.

Fix matrix.py:
- _mx_resolve_dm_room_async(client, mxid): scan rooms for 2-member DM,
  else room_create(is_direct, invite=[mxid], trusted_private_chat)
- mx_send_to_mxid(mxid, text) -> (ok, room_id): resolve + send
- mx_send docstring warns MXID-as-room_id pitfall

Fix a2a_delegate.py:
- call mx_send_to_mxid not mx_send(room_id=mxid)
- emit a2a_delegate_emitted log (corr+target+room) observability
- return room_id in JSON

Smoke 4/4 PASS.

refs SAIL-Research-Lab#80 SAIL-Research-Lab#38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants