Skip to content

feature/agent-memory-skills-and-unified-model - #135

Merged
cardosofede merged 286 commits into
mainfrom
feature/FEAT-003-stores-por-asistente
Jul 3, 2026
Merged

feature/agent-memory-skills-and-unified-model#135
cardosofede merged 286 commits into
mainfrom
feature/FEAT-003-stores-por-asistente

Conversation

@cardosofede

@cardosofede cardosofede commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

What changed

  1. Memory & Skills for AI agents (FEAT-001 → FEAT-003)
  • User memory (condor/memory/store.py): persistent file-per-fact store, exposed only via MCP (manage_memory), injected as [USER MEMORY] into /agent chat + trading-agent ticks.
    manage_notes is now a deprecated alias. New /memory command to review/prune.
  • Skills (condor/memory/skills.py): markdown playbooks (when-to-apply + steps) retrievable by relevance, can reference routines. New manage_skill MCP tool, injected as [SKILLS].
  • Per-assistant stores (FEAT-003): memory + skills are now scoped per assistant (condor chat and each trading agent get their own store) instead of shared per-user. Assistants moved to
    folder form (assistants/condor/AGENT.md); runtime stores gitignored.
  1. Unified Agent model (FEAT-004)
  • Merged "experts" and "strategies" into one Agent (condor/trading_agent/agent.py). An Agent is consultable (one-shot) and owns strategies that loop. experts.py and routes/experts.py
    removed; endpoints folded into routes/agents.py (/agents/{slug}/consult, /agents/{slug}/strategies/...). Migration script included.
  1. Frontend — Hyperliquid wallet connect
  • New ConnectHyperliquid flow with EVM/Hyperliquid wallet libs (lib/wallet/), agent+builder-code signup, referral prompt when wallet unfunded, unified balance dedupe.
  1. Quality wave (improvements backlog)
  • Security: WS auth via subprotocol (not query string), iframe sandboxing for reports, HTML escaping in chart tooltips, masked credential fields, cross-server WS leak fix, encoded URLs.
  • Perf: incremental candle updates, memoized chart/executor rows, WS subscription instead of polling, parallel snapshot fetches.
  • Refactor: extracted hooks (useBacktest, useResizeDrag), shared ExecutorTable/lib/backtest/lib/formatters, deduped helpers; trimmed dead agent UI components.
  1. Infra: pydantic-ai client overhaul, auto-generate JWT secret if absent, recursive AGENT.md file watcher, local-LLM (LM Studio) improvements, new test suites (test_agents,
    test_memory_store, test_skill_store).

QA recommendations

Migrations (run first, highest risk)

  • Run scripts/migrate_to_agent_model.py and the per-assistant store migration on a copy of prod data. Verify legacy data/notes/*.json and old shared stores migrate correctly and the
    legacy store is archived, not deleted.

Memory & Skills

  • In /agent, confirm the agent writes/edits/deletes a memory fact, and that /memory lists and prunes it. Verify edits made by one assistant are not visible to another assistant
    (isolation is the core FEAT-003 guarantee).
  • Create a skill via manage_skill, confirm it's injected into the next tick and the agent follows it; test a playbook that references a routine.

Unified Agent / trading agents

  • Consult an agent (/agents/{slug}/consult) and run a strategy loop — both paths share the same Agent. Confirm no broken imports (routes/experts.py removal was the original trigger).
    Verify existing brigado agent still ticks after migration.

Hyperliquid connect

  • Connect a wallet end-to-end; check funded vs unfunded wallet (referral signup prompt should appear), agent-name editing (16-char cap), and that unified Hyperliquid balances don't
    double-count.

Security regressions (verify the fixes hold)

  • WS connects with token in subprotocol (not URL); subscribe to a server you lack access to → must be rejected. Confirm report iframes are sandboxed and chart tooltips escape HTML.

Smoke / regression

  • Run uv run pytest (new + existing suites). Exercise dashboard pages touched by the refactor: Executors (new ExecutorTable), Backtesting (extracted hook), Portfolio, Reports, Agent
    detail — watch for empty tables or chart render regressions.
  • Confirm bot boots with no WEB_JWT_SECRET set (auto-generation) and AGENT.md edits hot-reload.

cardosofede and others added 30 commits June 17, 2026 17:34
TOKEN_KEY, authHeaders() y authFetch() viven ahora en un solo modulo.
api.ts, auth.ts, ChatInput (transcribe/FormData) y RoutineResultView
(AuthImage/blob) lo reutilizan en vez de redefinir "condor_token" y armar
el header Bearer a mano. El literal aparece una sola vez en src/.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
selectedTask/pinnedTask result se reparseaba (candles/executors, miles de
filas) en cada render: tipear en el form, polls de 2s y toasts. Ahora va en
useMemo keyed sobre la referencia cruda del result, estable entre renders de
react-query. Solo reparsea cuando llega data nueva de la task.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Los handlers de resize adjuntaban mousemove/mouseup a document en onMouseDown
y solo los removian en mouseup. Si el panel se desmontaba a mitad de un drag,
los listeners quedaban pegados y cursor/userSelect de document.body corruptos
globalmente. Ahora cada drag guarda su teardown en un ref y un useEffect de
unmount lo ejecuta. Aplicado en Executors, CreateExecutor (H y V) y
AgentFloatingPanel.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…026)

onLoaded/onError llamaban setOpenTabs del padre EditorTab desde el render body
del hijo (anti-patron "update a component while rendering"). Se mueve el manejo
de controllerQuery/configQuery a un useEffect keyed sobre data/isError/error,
guardado por loadedRef. El setState del padre se difiere a la fase de commit.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
El fin de cada bloque de tool-call se calculaba como
headers[i+1].index - name.length - 20, un offset magico que ignora
status.length y los digitos de N, cortando antes/despues del header siguiente
y contaminando la extraccion de Input/Output. Ahora se guarda start=match.index
y blockEnd = headers[i+1].start (exacto). Sin numeros magicos.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
saveMutation.onSuccess solo invalidaba caches para kind === config. Al guardar
un .py de controller, la query ['controller-source', ...] quedaba stale
(staleTime 5s global) y al reabrir el tab se servia el fuente pre-edicion. Se
agrega la rama else para controllers que invalida esa query.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
SessionExecutors fetcheaba los snapshots de a uno en un for await dentro del
queryFn, sumando N latencias antes de renderizar las burbujas del chart. Se
reemplaza por Promise.all sobre los summaries: corren concurrentemente, el
orden por tick se preserva y un snapshot que falla sigue dando burbuja
fallback. La latencia colapsa a la del request mas lento.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
configToYaml(config) (yaml.dump + sort) corria en cada render: tipear, toasts
y cada tick WS de bots que re-deriva config. Ademas el useEffect [config]
reseteaba yamlContent cada tick, pisando ediciones sin guardar. Ahora
originalYaml va en useMemo([config]) y el effect de sync se keyea sobre ese
string (comparado por valor): un tick con identidad nueva pero contenido igual
deja originalYaml estable y las ediciones sobreviven.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
AgentExperimentsTab, AgentSessionsTab, AgentToolbar, AgentFloatingPanel y
AgentRoutinesTab formaban una isla aislada sin importers externos (la UI viva
del agent usa SessionReviewer y AgentOverviewTab). Duplicaban la state machine
de routines y el render de snapshots de experimentos. Confirmado grep cero
referencias externas; tsc y vite build limpios.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…EAT-001)

Pure-filesystem MemoryStore keyed by user_id under data/memory/user_{id}/:
one fact per file (frontmatter + body), a regenerated MEMORY.md index, and a
JSONL audit.log. Atomic writes + reindex-from-disk make the index never stale
and safe under concurrent writers. search() is the single seam for future
semantic retrieval. 12 unit tests cover the lifecycle, atomicity and dedup.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… (FEAT-001)

manage_memory(write/read/search/list/delete/audit) resolves MemoryStore by
settings.user_id and derives the audit source from settings.agent_slug
(agent:<slug> vs chat), so both ACP and pydantic-ai backends get it for free.
manage_notes becomes a thin deprecated alias mapping onto the same store.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nts (FEAT-001)

build_initial_context appends the user's memory index (read on demand via
manage_memory) and swaps the deprecated manage_notes for manage_memory in the
ACP tool preload. condor.md and agent_builder.md get a MEMORY section telling
the agent when to read and write. Nothing is injected for users with no memory.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
build_tick_prompt gains an optional user_memory param rendered as a [USER MEMORY]
section (distinct from operational [LEARNINGS]); engine.py reads the owner's
memory index fresh each tick (small file read, never blocks a tick). MEMORY
guidance added to BASE_PROMPT_COMMON and manage_memory added to the ACP tool
preloads. Existing ticks without memory are unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New handlers/memory shows the user's memory index plus recent audit entries with
an inline delete button per memory; deletes go through MemoryStore.delete(...,
source="user") so they are audited too. Registered in main.py (command, callback,
bot-command menu).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…-001)

One-shot, idempotent script: resolves each chat_{id}.json to a user_id (the
chat_id itself for DMs, else the chat's default-server owner) and writes one
type="reference" memory per key/value. Existing slugs are skipped; source JSON
is left as backup. Ran over the 2 real note files -> 3 memories migrated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…te (FEAT-002)

A skill is a markdown playbook (when_to_use + steps) that optionally references
an existing routine. SkillStore mirrors MemoryStore 1:1 (file-per-skill + a
regenerable SKILLS.md index + the SHARED audit.log, target skill:<slug>).
read() validates references_routine against the routine registry and surfaces
routine_ok so the agent never invokes a broken reference. Extract append_audit
into a free function so memories and skills write the same format to the same
per-user audit.log. Unit tests cover create/list/read (with routine validation)/
search/edit/delete and the shared-audit guarantee.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Thin MCP wrapper over SkillStore (create/read/search/list/edit/delete),
resolving the store by settings.user_id and deriving the audit source from
settings.agent_slug — same pattern as manage_memory. Registered in server.py
with a docstring contract teaching when to create a skill and how a playbook
references a routine (routine_ok=false → don't invoke). Identical for ACP and
pydantic-ai since both connect to the same MCP server.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…h assistants (FEAT-002)

Chat (build_initial_context): inject the skills index as [SKILLS — playbooks you
can follow] alongside [USER MEMORY]; add manage_skill to the ToolSearch preload.
Trading agent (build_tick_prompt): unify the routines section into [AVAILABLE
SKILLS & ROUTINES] — skills first (read fresh each tick so an agent sees skills
it just created), routines after (cached). Teach BASE_PROMPT_COMMON and both
tool-preload strings. Teach condor.md / agent_builder.md to read a playbook
before a known flow and save reusable procedures; routine_builder.md gets the
playbook→routine bridge note.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extend /memory to show the user's skill playbooks (with their when_to_use and
routine-reference status) and a delete button per skill (callback delete_skill:,
routed to SkillStore.delete source="user"). The audit.log is already shared, so
skill writes/deletes already surfaced under "Recent changes". Closes FEAT-002:
move the design doc to features/done/ with status done and commit trail.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Point the commits[] close entry at the actual close commit (fdb52c9); a
commit cannot self-reference its own post-amend hash, so this is a small
follow-up bookkeeping commit.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
cardosofede and others added 20 commits July 2, 2026 14:38
AuthImage rendered null until the authenticated blob fetch resolved, then
popped in a full-width img that pushed the table/raw-output sections down
(large CLS on every report open and instance switch). Now shows a pulsing
aspect-[2/1] placeholder while loading and keeps the same aspect box (with
object-contain) on the loaded img; failed fetches still collapse to null.

Closes PERF-090.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replace hand-rolled `${x >= 0 ? "+" : ""}{x.toFixed(2)}` PnL soup and raw
toLocaleString volumes with formatCurrencyPnl/formatCurrencyVolume/
formatCurrency from lib/formatters, matching Portfolio: negatives render
"-$12.34" (not "$-12.34") and large values compact to K/M.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The amber Agent pill and the synthetic Cmd+K KeyboardEvent hack were
copy-pasted across AppShell, ControllerBrowser and ReportBrowser. Extract
frontend/src/components/layout/AgentToggleButton.tsx encapsulating the pill
styling and the chat-toggle trigger; AppShell passes its active state and
own onClick, the two browsers render the shared component.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…RR-098)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s crosshair (PERF-091)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
READ-062: the DRY RUN / RUN ONCE badge ternary was duplicated
character-for-character in Agents.tsx and AgentOverviewTab.tsx, and
SessionReviewer.tsx encoded the same mode-to-color concept a third way.
Centralize it as MODE_STYLES (modeStyles.ts) + ModeBadge component,
mirroring the STATUS_STYLES/StatusBadge split. SessionReviewer's compact
sidebar keeps its icon+short-label UI and shares only the color map.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tors/Bots pages (READ-075)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…o-server pages (READ-076)

Replaces the bare 'Select a server' text on Executors, Active Bots, Runs,
Routines, Editor, Backtesting, Create Executor, Create Grid Executor and
Archived Bots with the explanatory card Portfolio already had, now extracted
to components/NoServerCard.tsx with a 'Go to Settings -> Servers' action.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…EAD-099)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replace hardcoded text-emerald-400/text-red-400 on PnL numbers and
buy/sell sides with text-[var(--color-green)]/text-[var(--color-red)]
so the colorblind theme (blue/orange) and light theme apply correctly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Nine hand-rolled modals (EditorDialogs x4, StopConfirmDialog,
CreateAgentDialog, CreateStrategyDialog + delete confirms,
StartSessionDialog, DeployBotDialog) only closed via backdrop or
Cancel. Extract the inline Escape effect into useEscapeKey and wire
it into every dialog, replacing the duplicated inline effects in
AgentDetail and StrategyDetail. Also covers the newer
DeleteAgentDialog in Agents.tsx (CORR-077).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Closing a tab whose content differed from originalContent silently
discarded unsaved YAML/Python edits. The tab-bar X now routes through
requestCloseTab: dirty tabs open a DiscardChangesDialog (same pattern
as DeleteConfirmDialog, with Escape support) offering Discard changes /
Keep editing; clean tabs still close instantly. The post-delete cleanup
path keeps closing directly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s (CORR-093)

MarkdownEditor now reports dirtiness via an optional onDirtyChange prop.
StrategyDetail and AgentDetail route backdrop click, Escape and the X
button through a guard: with unsaved edits they open the shared
DiscardChangesDialog instead of silently unmounting the editor; clean
modals close exactly as before, and a successful save resets the guard.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Extract a shared ConfirmDialog component and route the three copy-pasted
delete-confirm modals (Agents.tsx DeleteAgentDialog, AgentDetail agent and
strategy deletes) through it. Its destructive button uses the themed
bg-[var(--color-red)] token instead of hardcoded bg-red-500, so agent deletes
now honor the colorblind theme's red remap and match the editor dialogs. The
dialog also closes on Escape internally via useEscapeKey, replacing the two
parent-level registrations in AgentDetail.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nt PnL charts on theme switch (CORR-057)

Extend ThemeColors with bg/grid/text and delete the four private
getChartColors() copies (TradeChart, ExecutorChart, AgentPnlChart,
ArchivedPerformanceCharts) that each called getComputedStyle directly,
routing them through the cached getThemeColors() in lib/theme-colors.ts.

Replicate TradeChart's data-theme MutationObserver in ExecutorChart and
AgentPnlChart so switching dark/light repaints chart background/grid/text
immediately instead of leaving stale colors until remount.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add Escape handling and aria-expanded/aria-haspopup to ServerSelector,
CurrencySelector, the shared SelectField, and the backtest config picker,
matching the existing PairSelector keyboard pattern (CORR-082).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@rapcmia

rapcmia commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Commit 36ae26a

  • Rebuild docker image and use make setup; make deploy

Retest c1e34c0 dashboard rendering only where output formatting changed:

  • Consult answer markdown rendering ✅
    image
  • Use delegation on agent consult page ✅
    image
  • I test condor/consult on Gate.io BTC-USDT Spot Test Maker returned a delegate-style response for a different agent ❌
    image
    ✅ Tool: condor/consult (16s)
    
    I’m checking the most likely cause of that mismatch, because a consult should not normally come back with a background-delegation message unless the consulted agent itself decided to hand work off or crossed wires with another agent.Most likely, the consult did run, but the consulted Gate.io agent itself responded by calling delegate internally.
    
    That would explain both symptoms:
    - you used consult
    - but the returned text looked like a delegation confirmation
    - and it mentioned the wrong agent, KuCoin SOL-USDT, which points to bad cross-routing or stale instructions/context inside the Gate.io agent
    
    So the mismatch is probably not “consult turned into delegate” at the platform level. It’s more likely:
    - consult invoked the Gate.io agent correctly
    - the Gate.io agent then chose the wrong action internally
    - it delegated to another agent and surfaced that delegation message back to you
    
    Why the KuCoin name appeared:
    - cross-agent routing mistake in the Gate.io agent’s instructions
    - stale context or copied logic referencing the KuCoin agent
    - a too-broad “delegate long-running tasks” behavior inside that agent
    
    Short version:
    - outer tool: consult
    - inner behavior: mistaken delegate
    - wrong target: likely agent misconfiguration
    
  • The agent chat on webui supports delegate ✅
    image
    image
  • Check consult rendering for invalid tool-response errors ✅
    #### Consult page payload
    Use connector fakeexchange for BTC-USDT, fetch the live order book, and return the raw tool error exactly as received.
    
    image

Retest FEAT-007 shutdown behavior end to end in progress

  • End-to-end validation of the Stop and Shutdown workflows completed successfully
  • Confirmed Shutdown successfully stopped a live bot, cleared active orders, and kept the spot balance intact.
  • Verified Shutdown follows a different flow than the regular Stop command.
  • Todo: Retest drawdown thresholds e.g max drawdowns, etc. ❗

Retest server pinning behavior introduced in 35d1099 and surfaced in 36ae26a

image
  • The request-side consult guard correctly rejected an unauthorized server selection. When a limited user called consult with server_name: local, the request returned 403 No access. ✅
  • create agent with pinned server ✅
  • I consulted the pinned-server probe agent after explicitly including the agent name, and it used the pinned server correctly.
  • Started a strategy under that same agent, and it also used the pinned server.
    pinned_server_probe | Tick #1
    Agent: pinned_server_probe.pinned_server_loop_2
    Status: Pinned-server verification loop active. No trading.
    Configured pinned server: visible via agent config (runtime server not directly exposed in tool context).
    Action: Hold — no executors created.
    

cardosofede and others added 5 commits July 2, 2026 18:28
Extract the byte-for-byte identical PnlTooltip/BottomTooltip components out
of AggregatedPnlChart and ControllerPnlChart into a shared
components/bots/PnlChartTooltips.tsx, and centralize the fixed series colors
(unrealized/volume/position) as PNL_SERIES_COLORS in lib/pnl-chart.ts so
strokes, axis ticks, header stats and tooltips reference one source.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Render at most 100 rows initially with a "Show N more" control instead of
mounting all up to ~2000 archived executors (~26k DOM cells) at once.
Sorting still runs on the full array so top-N by any column stays correct;
select-all/CSV/aggregates are computed in the parent from full arrays and
are unaffected. No new dependency (no virtualization lib installed).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@rapcmia

rapcmia commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Commit 99a4752

  • Setup on source + HAPI (docker)

Retest agents routes and strategy lifecycle, especially /agents/delegations behavior ✅

  • Retest on 99a4752 for the earlier route-access setup gap after Condor source was started.
  • Logged in through the Condor web-token flow and confirmed auth worked.
  • /api/v1/agents/delegations returned the delegations list successfully
  • Fake-task checks on the detail and stop routes returned delegation-specific 404 responses, which confirms these routes are not being recognized by the slug
      curl -s http://localhost:8088/api/v1/agents/delegations/test-task \
        -H "Authorization: Bearer XXX" | jq
    
      {
        "detail": "Delegation 'test-task' not found"
      }
    
      curl -s -X POST http://localhost:8088/api/v1/agents/delegations/test-task/stop \
        -H "Authorization: Bearer XXX" | jq
    
      {
        "detail": "Delegation 'test-task' not found"
      }
    

Re-test bots page parity between REST and websocket updates, including stopping overlays and controller PnL data. ✅

  • Opened the bots page with a live bot/controller already running and saw the bots status, controllers status, and PNL as soon as the page loaded
  • Left the page open and watched websocket updates come through without refreshing while i triggered pause/resume, a filled order event and stop
  • The stopping overlay appear while shutdown was in progress and disappear after the bot fully stopped and archived

Re-test chat permission isolation with two users. ✅

  • User A was the admin user and User B was only approved as a normal user, so this retest stayed focused on the condor/consult path and not on broader trading-agent loop behavior.
  • User B could still access Condor chat, but when User B tried the direct consult flow the request returned 403 instead of reusing User A's server-backed access or agent context.
  • This confirms the two-user isolation on the consult path: approved chat access for User B did not turn into inherited admin consult permission.

Re-test risk gating for repeated executor creates in one tick and tracker-failure handling. ✅

| Field | Value |
|---|---|
| Action | BUY LIMIT_MAKER placed |
| Price | $61,583.26 |
| Amount | 0.000116 BTC (~$7.16) |
| Executor ID | `2tWszhjNigpU...` |
| SELL side | Skipped (1-executor limit) |
| Rebalance | Not needed ($6.93 deviation) |

**Note:** The 1-executor open limit prevents two-sided quoting simultaneously. BUY was prioritized since USDT is slightly over-weight (57.4%). On the next tick, if this executor fills or expires, the SELL side can be placed to rebalance.
  • Gate.io BTC-USDT retest on gateio_btc_usdt_spot_test_maker / gateio_btc_usdt_spot_test_loop session 12 allowed the first create and then stopped the second create path in the same tick.
  • Condor route evidence matched the report: session 12 journal recorded Placed BUY LIMIT_MAKER 0.000116 BTC @ $61,583.26 with executor 2tWszhjNigpURhu4YdPjRex4LtLn5HhfVAMjVBARmYCp, and snapshot #1 showed SELL side | Skipped (1-executor limit).
  • Since the max_executor is set to 1, it only placed sell order

Manually validate the new Market Making Expert consult/delegate flow. ✅

  • Test API route
    curl -s http://localhost:8088/api/v1/agents/market_making_expert/consult \
        -H "Authorization: Bearer XXX" \
        -H "Content-Type: application/json" \
        -d '
      {
        "task": "QA validation only: explain in 2 short bullets when Market Making Expert should be consulted vs delegated. Do not deploy anything.",
        "context": "Testing the new consult/delegate flow for Condor source.",
        "chat_id": 0
      }' | jq
    
    {
      "agent": "market_making_expert",
      "answer": "- **Consult** when you need advisory output inline — regime assessment, spread calibration, inventory review, or config tuning — without touching any live bots.\n- **Delegate** when you want a full bot deployment run
      autonomously in the background — the agent reads `pmm_mister_deploy` and executes the end-to-end flow (regime → config → deploy) without mid-flow user confirmation."
    }
    
    ---
    
    curl -s http://localhost:8088/api/v1/agents/market_making_expert/delegate \
      -H "Authorization: Bearer XXX" \
      -H "Content-Type: application/json" \
      -d '
    {
      "task": "QA validation only: return a short background confirmation message for delegate flow. Do not deploy, trade, or edit files.",
      "chat_id": 0,
      "timeout_s": 120
    }' | jq
    
    {
      "task_id": "market_making_expert-delegate-e08d80b6",
      "status": "running"
    }
    
    ---
    
    curl -s http://localhost:8088/api/v1/agents/delegations/market_making_expert-delegate-e08d80b6 \
      -H "Authorization: Bearer XXX" | jq
    
    {
      "task_id": "market_making_expert-delegate-e08d80b6",
      "agent": "market_making_expert",
      "user_id": 1474408604,
      "chat_id": 0,
      "server_name": null,
      "task": "QA validation only: return a short background confirmation message for delegate flow. Do not deploy, trade, or edit files.",
      "status": "done",
      "result": "Background delegate confirmed. Market Making Expert agent is active and ready. No deployment, trading, or file changes initiated — standing by for task assignment.",
      "error": ""
    }
    
  • Test using telegram
    image
    image

@rapcmia rapcmia left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Memory separation worked across Condor chat, trading-agent flows, and Routine Builder style routine access.
  • The unified agent migration worked: Telegram trading-agent loops still ran, and Condor consult reached the correct unified agent path.
  • Trading-agent session launch now carries the correct user identity through CONDOR_USER_ID.
  • Condor web login worked correctly, including one-time token use, redirect to the right page, and token invalidation after reuse/logout.
  • Protected Condor routes enforced auth correctly, and authenticated agent/delegation routes resolved as expected.
  • Access isolation worked: a normal approved user could not reuse an admin user's server-backed consult access.
  • server_required=true behavior improved: consult was blocked for no-server users, and launch was also stopped in practice when required checks could not complete.
  • Normal consult still worked for the matching non-server-required setup.
  • Bots page data stayed consistent between REST and websocket updates, including status, PnL, and stopping overlays.
  • Delegation flow worked end to end: delegation routes resolved correctly, background tasks completed, and results could be fetched separately.
  • Consult and delegation responses rendered clearly in the UI, including markdown tables, headings, bullets, and readable error output.
  • The new Market Making Expert flow worked as intended: consult returned inline advice, while delegate ran in the background and finished separately.
  • Risk gating blocked repeated executor creation in the same tick after the first approved create.
  • FEAT-007 shutdown behavior worked end to end and stayed distinct from normal Stop.
  • Dry-run startup no longer showed the earlier obvious journal-write failure.
  • Strategy detail correctly showed saved Dry run counts.
  • The live hummingbot-api gateway docs no longer showed a passphrase field.
  • The Routines page worked in both grid and table views, including search, sorting, and linked report navigation.
  • Server pinning worked correctly at runtime once the pinned agent/strategy path was tested directly.

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.

5 participants