fix(cowork-service): audit flush field name mismatch + server test mock gap
BUG: flush-scheduler.ts flushAudit() read 'events' from IPC response but
Rust handle_flush_audit() returns { count, entries }. Audit events were
silently lost (always empty array). Fixed to read 'entries'.
Also fixed:
- server.test.ts: added missing flush-scheduler.js mock (new import in server.ts)
- feature-flags.ts: doc comment '12 flags' → '13 flags'
- flush-scheduler.test.ts: mock data aligned to Rust response shape
49 tests passing, 8 test files, typecheck clean.
This commit is contained in:
parent
9fc5af5b2b
commit
53c3565874
@ -1,8 +1,12 @@
|
|||||||
# All workspace repositories
|
# All workspace repositories — SINGLE SOURCE OF TRUTH
|
||||||
# Single source of truth for repo-management workflows
|
# Used by all /repo_* workflows and scripts (backup, commit, push, sync, agent-docs)
|
||||||
# Reference this file in scripts instead of hardcoding repo lists
|
# Paths are relative to ~/code/mygh/ (the workspace root)
|
||||||
|
# To add a new repo: append its path here and all workflows will pick it up automatically
|
||||||
|
|
||||||
|
# --- Platform & shared ---
|
||||||
learning_ai_common_plat
|
learning_ai_common_plat
|
||||||
|
|
||||||
|
# --- Product repos ---
|
||||||
learning_voice_ai_agent
|
learning_voice_ai_agent
|
||||||
learning_multimodal_memory_agents
|
learning_multimodal_memory_agents
|
||||||
learning_ai_clock
|
learning_ai_clock
|
||||||
@ -13,6 +17,16 @@ learning_ai_notes
|
|||||||
learning_ai_flowmonk
|
learning_ai_flowmonk
|
||||||
learning_ai_trails
|
learning_ai_trails
|
||||||
learning_ai_local_memory_gpt
|
learning_ai_local_memory_gpt
|
||||||
|
learning_ai_efforise
|
||||||
|
learning_ai_local_llms
|
||||||
|
|
||||||
|
# --- Auth & identity ---
|
||||||
learning_ai_smart_auth
|
learning_ai_smart_auth
|
||||||
learning_ai_auth_app
|
learning_ai_auth_app
|
||||||
|
|
||||||
|
# --- Web & misc ---
|
||||||
learning_ai_productivity_web
|
learning_ai_productivity_web
|
||||||
|
|
||||||
|
# --- OSS (subdirectory repos under oss/) ---
|
||||||
|
oss/learning_ai_claw-code-oss
|
||||||
|
oss/learning_ai_claw-cowork
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
Last refresh: 2026-04-02T17:27:25Z (2026-04-02 10:27:25 PDT)
|
Last refresh: 2026-04-03T06:00:06Z (2026-04-02 23:00:06 PDT)
|
||||||
Cascade conversations: 50 (330M)
|
Cascade conversations: 50 (297M)
|
||||||
Memories: 119
|
Memories: 121
|
||||||
Implicit context: 20
|
Implicit context: 20
|
||||||
Code tracker dirs: 102
|
Code tracker dirs: 106
|
||||||
File edit history: 4201 entries
|
File edit history: 4222 entries
|
||||||
Workspace storage: 37 workspaces
|
Workspace storage: 37 workspaces
|
||||||
Repo docs: 7 files across 2 repos
|
Repo docs: 7 files across 2 repos
|
||||||
Repo workflows: 54 files across 12 repos
|
Repo workflows: 54 files across 12 repos
|
||||||
|
|||||||
@ -1,8 +1,12 @@
|
|||||||
# All workspace repositories
|
# All workspace repositories — SINGLE SOURCE OF TRUTH
|
||||||
# Single source of truth for repo-management workflows
|
# Used by all /repo_* workflows and scripts (backup, commit, push, sync, agent-docs)
|
||||||
# Reference this file in scripts instead of hardcoding repo lists
|
# Paths are relative to ~/code/mygh/ (the workspace root)
|
||||||
|
# To add a new repo: append its path here and all workflows will pick it up automatically
|
||||||
|
|
||||||
|
# --- Platform & shared ---
|
||||||
learning_ai_common_plat
|
learning_ai_common_plat
|
||||||
|
|
||||||
|
# --- Product repos ---
|
||||||
learning_voice_ai_agent
|
learning_voice_ai_agent
|
||||||
learning_multimodal_memory_agents
|
learning_multimodal_memory_agents
|
||||||
learning_ai_clock
|
learning_ai_clock
|
||||||
@ -13,6 +17,16 @@ learning_ai_notes
|
|||||||
learning_ai_flowmonk
|
learning_ai_flowmonk
|
||||||
learning_ai_trails
|
learning_ai_trails
|
||||||
learning_ai_local_memory_gpt
|
learning_ai_local_memory_gpt
|
||||||
|
learning_ai_efforise
|
||||||
|
learning_ai_local_llms
|
||||||
|
|
||||||
|
# --- Auth & identity ---
|
||||||
learning_ai_smart_auth
|
learning_ai_smart_auth
|
||||||
learning_ai_auth_app
|
learning_ai_auth_app
|
||||||
|
|
||||||
|
# --- Web & misc ---
|
||||||
learning_ai_productivity_web
|
learning_ai_productivity_web
|
||||||
|
|
||||||
|
# --- OSS (subdirectory repos under oss/) ---
|
||||||
|
oss/learning_ai_claw-code-oss
|
||||||
|
oss/learning_ai_claw-cowork
|
||||||
|
|||||||
@ -174,6 +174,28 @@ set_meta() {
|
|||||||
LINT2="cd android && ./gradlew :app:assembleDebug 2>&1 | tail -20"
|
LINT2="cd android && ./gradlew :app:assembleDebug 2>&1 | tail -20"
|
||||||
AIDER_READ2="README.md"
|
AIDER_READ2="README.md"
|
||||||
;;
|
;;
|
||||||
|
learning_ai_efforise)
|
||||||
|
NAME="EffoRise"
|
||||||
|
ID="efforise"
|
||||||
|
TAGLINE="Identity-based habit tracker"
|
||||||
|
STACK="Vite + React 19 SPA (client/) + Fastify 5 backend (backend/) + React Native/Expo (mobile/) + @bytelyst/* shared packages"
|
||||||
|
BUILD_VFY="cd backend && pnpm test && pnpm run typecheck && pnpm run build"
|
||||||
|
LINT1="cd backend && pnpm test 2>&1 | tail -10"
|
||||||
|
LINT2="cd backend && pnpm run typecheck 2>&1 | tail -10"
|
||||||
|
LINT3="cd backend && pnpm run build 2>&1 | tail -10"
|
||||||
|
AIDER_READ2="README.md"
|
||||||
|
;;
|
||||||
|
learning_ai_local_llms)
|
||||||
|
NAME="Local LLM Lab"
|
||||||
|
ID="localllmlab"
|
||||||
|
TAGLINE="Personal local AI inference toolkit"
|
||||||
|
STACK="Next.js 16 (dashboard) + Ollama + @bytelyst/llm-router + Python (TTS)"
|
||||||
|
BUILD_VFY="cd dashboard && pnpm test && pnpm typecheck && pnpm build"
|
||||||
|
LINT1="cd dashboard && pnpm test 2>&1 | tail -10"
|
||||||
|
LINT2="cd dashboard && pnpm typecheck 2>&1 | tail -10"
|
||||||
|
LINT3="cd dashboard && pnpm build 2>&1 | tail -10"
|
||||||
|
AIDER_READ2="README.md"
|
||||||
|
;;
|
||||||
learning_ai_productivity_web)
|
learning_ai_productivity_web)
|
||||||
NAME="Productivity Web"
|
NAME="Productivity Web"
|
||||||
ID="(internal)"
|
ID="(internal)"
|
||||||
@ -184,6 +206,28 @@ set_meta() {
|
|||||||
LINT2="npm run build 2>&1 | tail -10"
|
LINT2="npm run build 2>&1 | tail -10"
|
||||||
AIDER_READ2="README.md"
|
AIDER_READ2="README.md"
|
||||||
;;
|
;;
|
||||||
|
oss/learning_ai_claw-code-oss)
|
||||||
|
NAME="Claw Code OSS"
|
||||||
|
ID="(upstream)"
|
||||||
|
TAGLINE="Upstream Claude Code OSS fork — runtime, API, and tools crates"
|
||||||
|
STACK="Rust (workspace) + Python + TypeScript"
|
||||||
|
BUILD_VFY="cargo build --workspace && cargo test --workspace"
|
||||||
|
LINT1="cargo fmt --check 2>&1 | tail -10"
|
||||||
|
LINT2="cargo clippy --workspace --all-targets -- -D warnings 2>&1 | tail -10"
|
||||||
|
LINT3="cargo test --workspace 2>&1 | tail -10"
|
||||||
|
AIDER_READ2="README.md"
|
||||||
|
;;
|
||||||
|
oss/learning_ai_claw-cowork)
|
||||||
|
NAME="Claw Cowork"
|
||||||
|
ID="clawcowork"
|
||||||
|
TAGLINE="Desktop agent for complex multi-step knowledge work with Docker sandboxing"
|
||||||
|
STACK="Rust (workspace) + React/TypeScript (Tauri frontend) + Python (skills server)"
|
||||||
|
BUILD_VFY="cargo build --workspace && cargo test --workspace"
|
||||||
|
LINT1="cargo fmt --check 2>&1 | tail -10"
|
||||||
|
LINT2="cargo clippy --workspace --all-targets -- -D warnings 2>&1 | tail -10"
|
||||||
|
LINT3="cargo test --workspace 2>&1 | tail -10"
|
||||||
|
AIDER_READ2="COWORK.md"
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
warn "Unknown repo: $1 — skipping"
|
warn "Unknown repo: $1 — skipping"
|
||||||
return 1
|
return 1
|
||||||
@ -299,6 +343,22 @@ repo_rules() {
|
|||||||
echo "- Theme via BLAuthUIConfig (iOS) / MaterialTheme (Android)"
|
echo "- Theme via BLAuthUIConfig (iOS) / MaterialTheme (Android)"
|
||||||
echo "- Never create a separate backend — app talks to platform-service"
|
echo "- Never create a separate backend — app talks to platform-service"
|
||||||
;;
|
;;
|
||||||
|
learning_ai_efforise)
|
||||||
|
echo "- Backend follows the ByteLyst product-backend pattern with Fastify 5 + TypeScript ESM"
|
||||||
|
echo "- Use @bytelyst/* shared packages instead of reimplementing common infrastructure"
|
||||||
|
echo "- Fastify modules follow types.ts → repository.ts → routes.ts"
|
||||||
|
echo "- Use req.log / app.log — never console.log"
|
||||||
|
echo "- Every Cosmos document MUST include productId: \"efforise\""
|
||||||
|
echo "- Theme tokens use --er-* CSS custom properties — never hardcode colors"
|
||||||
|
;;
|
||||||
|
learning_ai_local_llms)
|
||||||
|
echo "- Dashboard uses server-side routing — keep UI as thin client"
|
||||||
|
echo "- @bytelyst/llm-router from Gitea npm registry (not file: ref)"
|
||||||
|
echo "- Never commit model weights (.gguf, .bin, .safetensors)"
|
||||||
|
echo "- Never hardcode Ollama URLs — use OLLAMA_HOST env var"
|
||||||
|
echo "- Corporate proxy: use hf-mirror.com instead of huggingface.co"
|
||||||
|
echo "- CSS tokens use --llm-* prefix"
|
||||||
|
;;
|
||||||
learning_ai_productivity_web)
|
learning_ai_productivity_web)
|
||||||
echo "- App Router pages live in src/app/"
|
echo "- App Router pages live in src/app/"
|
||||||
echo "- Reusable UI lives in src/components/"
|
echo "- Reusable UI lives in src/components/"
|
||||||
@ -306,6 +366,21 @@ repo_rules() {
|
|||||||
echo "- Keep UI changes thin and tool-registry-driven where possible"
|
echo "- Keep UI changes thin and tool-registry-driven where possible"
|
||||||
echo "- Avoid inventing APIs or hidden backend contracts"
|
echo "- Avoid inventing APIs or hidden backend contracts"
|
||||||
;;
|
;;
|
||||||
|
oss/learning_ai_claw-code-oss)
|
||||||
|
echo "- Upstream claw-code fork — do NOT add custom features here"
|
||||||
|
echo "- Periodically pull from upstream and merge"
|
||||||
|
echo "- Rust crates: runtime, api, tools (consumed by claw-cowork)"
|
||||||
|
echo "- Python client: tests/, scripts/"
|
||||||
|
echo "- TypeScript SDK: ts-sdk/"
|
||||||
|
;;
|
||||||
|
oss/learning_ai_claw-cowork)
|
||||||
|
echo "- Docker-first sandbox — native VM backends are stubs"
|
||||||
|
echo "- Python skills inside sandbox for document processing"
|
||||||
|
echo "- Tauri v2 for desktop GUI — Rust backend + React frontend"
|
||||||
|
echo "- Async architecture — bollard (Docker API) is async"
|
||||||
|
echo "- Base64 encoding for file content passed to sandbox"
|
||||||
|
echo "- Use conventional commit prefixes: feat(), fix(), docs:, test:, refactor:"
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -405,12 +480,42 @@ repo_paths() {
|
|||||||
echo "- shared/product.json — canonical product identity"
|
echo "- shared/product.json — canonical product identity"
|
||||||
echo "- ios/project.yml and android/ build files — native project wiring"
|
echo "- ios/project.yml and android/ build files — native project wiring"
|
||||||
;;
|
;;
|
||||||
|
learning_ai_efforise)
|
||||||
|
echo "- client/ — Vite + React 19 SPA"
|
||||||
|
echo "- backend/ — Fastify 5 + TypeScript ESM backend (port 4020)"
|
||||||
|
echo "- backend/src/modules/ — identities, efforts, habits, streaks, insights"
|
||||||
|
echo "- mobile/ — React Native + Expo (SDK 55) companion app"
|
||||||
|
echo "- mobile/src/app/(tabs)/ — 5-tab navigator (Home, Identity, Log, Insights, Settings)"
|
||||||
|
;;
|
||||||
|
learning_ai_local_llms)
|
||||||
|
echo "- dashboard/ — Mission Control Next.js 16 app"
|
||||||
|
echo "- dashboard/src/app/api/ — Ollama proxy, Whisper, TTS, system info"
|
||||||
|
echo "- dashboard/src/app/(mission-control)/ — System overview, model management"
|
||||||
|
echo "- tts/ — TTS setup scripts + experiments"
|
||||||
|
echo "- scripts/ — start-dashboard.sh + windows setup"
|
||||||
|
echo "- experiments/ — oss-llm, open-claw, voicebox"
|
||||||
|
;;
|
||||||
learning_ai_productivity_web)
|
learning_ai_productivity_web)
|
||||||
echo "- src/app/ — App Router pages and routes"
|
echo "- src/app/ — App Router pages and routes"
|
||||||
echo "- src/components/ — Navbar and tool cards"
|
echo "- src/components/ — Navbar and tool cards"
|
||||||
echo "- src/lib/ — utility and tool registry helpers"
|
echo "- src/lib/ — utility and tool registry helpers"
|
||||||
echo "- next.config.ts, tailwind.config.ts — web app configuration"
|
echo "- next.config.ts, tailwind.config.ts — web app configuration"
|
||||||
;;
|
;;
|
||||||
|
oss/learning_ai_claw-code-oss)
|
||||||
|
echo "- rust/crates/runtime/ — ConversationRuntime, Session, PermissionPolicy"
|
||||||
|
echo "- rust/crates/api/ — AnthropicClient, AuthSource, SSE streaming"
|
||||||
|
echo "- rust/crates/tools/ — ToolSpec, tool dispatch"
|
||||||
|
echo "- python/ — Python client SDK"
|
||||||
|
echo "- ts-sdk/ — TypeScript SDK"
|
||||||
|
;;
|
||||||
|
oss/learning_ai_claw-cowork)
|
||||||
|
echo "- crates/cowork-vm/ — Sandbox lifecycle (Docker, VZ abstraction)"
|
||||||
|
echo "- crates/cowork-orchestrator/ — Task coordination, LLM planner, plugins, MCP"
|
||||||
|
echo "- crates/cowork-skills/ — Rust↔Python bridge for document processing"
|
||||||
|
echo "- crates/cowork-desktop/ — Tauri v2 desktop app (Rust + React)"
|
||||||
|
echo "- docker/ — Dockerfile + Python skills server"
|
||||||
|
echo "- connectors/ — MCP connector servers (Google Drive, Gmail, GCal, Slack)"
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* Feature flag registry for cowork-service.
|
* Feature flag registry for cowork-service.
|
||||||
*
|
*
|
||||||
* Defaults match the 12 platform flags seeded in H.1
|
* Defaults match the 13 platform flags seeded in H.1
|
||||||
* (platform-service/src/modules/flags/seed.ts clawcowork entry).
|
* (platform-service/src/modules/flags/seed.ts clawcowork entry).
|
||||||
*/
|
*/
|
||||||
import { createFlagRegistry } from '@bytelyst/backend-flags';
|
import { createFlagRegistry } from '@bytelyst/backend-flags';
|
||||||
|
|||||||
@ -45,7 +45,7 @@ const mockLog = {
|
|||||||
function createMockBridge(running = true) {
|
function createMockBridge(running = true) {
|
||||||
return {
|
return {
|
||||||
isRunning: running,
|
isRunning: running,
|
||||||
flushAudit: vi.fn().mockResolvedValue({ result: { count: 2, events: [
|
flushAudit: vi.fn().mockResolvedValue({ result: { count: 2, entries: [
|
||||||
{ userId: 'u1', action: 'task.submit', category: 'task', details: {} },
|
{ userId: 'u1', action: 'task.submit', category: 'task', details: {} },
|
||||||
{ userId: 'u2', action: 'task.cancel', category: 'task', details: {} },
|
{ userId: 'u2', action: 'task.cancel', category: 'task', details: {} },
|
||||||
] } }),
|
] } }),
|
||||||
@ -133,7 +133,7 @@ describe('FlushScheduler', () => {
|
|||||||
|
|
||||||
it('handles empty IPC responses', async () => {
|
it('handles empty IPC responses', async () => {
|
||||||
const bridge = createMockBridge(true);
|
const bridge = createMockBridge(true);
|
||||||
bridge.flushAudit.mockResolvedValue({ result: { count: 0, events: [] } });
|
bridge.flushAudit.mockResolvedValue({ result: { count: 0, entries: [] } });
|
||||||
bridge.flushTelemetry.mockResolvedValue({ result: { count: 0, events: [] } });
|
bridge.flushTelemetry.mockResolvedValue({ result: { count: 0, events: [] } });
|
||||||
bridge.flushBudget.mockResolvedValue({ result: { count: 0, records: [] } });
|
bridge.flushBudget.mockResolvedValue({ result: { count: 0, records: [] } });
|
||||||
vi.mocked(getIpcBridge).mockReturnValue(bridge as unknown as ReturnType<typeof getIpcBridge>);
|
vi.mocked(getIpcBridge).mockReturnValue(bridge as unknown as ReturnType<typeof getIpcBridge>);
|
||||||
|
|||||||
@ -115,7 +115,8 @@ export class FlushScheduler {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const r = resp.result as Record<string, unknown> | undefined;
|
const r = resp.result as Record<string, unknown> | undefined;
|
||||||
const entries: AuditEntry[] = (r?.events as AuditEntry[]) ?? [];
|
// Rust flush_audit returns { count, entries } — NOT "events"
|
||||||
|
const entries: AuditEntry[] = (r?.entries as AuditEntry[]) ?? [];
|
||||||
if (entries.length === 0) return { drained: 0, posted: 0, errors: 0 };
|
if (entries.length === 0) return { drained: 0, posted: 0, errors: 0 };
|
||||||
|
|
||||||
const { posted, errors } = await postAuditEvents(entries);
|
const { posted, errors } = await postAuditEvents(entries);
|
||||||
|
|||||||
@ -54,6 +54,14 @@ vi.mock('./lib/ipc-bridge.js', () => ({
|
|||||||
shutdown: vi.fn(async () => undefined),
|
shutdown: vi.fn(async () => undefined),
|
||||||
})),
|
})),
|
||||||
}));
|
}));
|
||||||
|
vi.mock('./lib/flush-scheduler.js', () => ({
|
||||||
|
getFlushScheduler: vi.fn(() => ({
|
||||||
|
isRunning: false,
|
||||||
|
start: vi.fn(),
|
||||||
|
stop: vi.fn(),
|
||||||
|
finalFlush: vi.fn(async () => undefined),
|
||||||
|
})),
|
||||||
|
}));
|
||||||
|
|
||||||
describe('cowork-service bootstrap', () => {
|
describe('cowork-service bootstrap', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user