Commit Graph

466 Commits

Author SHA1 Message Date
b4403300fa chore(nomgap): finalize product deployment config
What changed:
- Remove nomgap-web from the ecosystem Docker stack now that web is Vercel-hosted.
- Add a TODO for deciding whether local Docker smoke tests still need a NomGap web service.
- Update NomGap product containers and feature flags.
- Seed the NomGap push trigger flag without duplicating the common encryption flag.

Safety notes:
- Dropped unrelated pnpm-lock.yaml formatting churn instead of committing it.

Verification:
- node JSON.parse products/nomgap/product.json
- ruby Psych.safe_load docker-compose.ecosystem.yml
- pnpm --filter @bytelyst/admin-web typecheck
- pnpm --filter @bytelyst/admin-web test
- pnpm --filter @bytelyst/admin-web exec eslint . --ext .ts,.tsx
- pnpm --filter @lysnrai/platform-service build
- pnpm --filter @lysnrai/platform-service test
- pnpm --filter @lysnrai/platform-service exec eslint . --ext .ts,.tsx
- pnpm typecheck
- pnpm lint
2026-05-04 16:29:20 -07:00
021f053143 chore(platform): type predictive campaign events
What changed:
- Replaced predictive campaign-engine event-bus any casts with typed bus.emit calls.
- Preserved existing fire-and-forget event dispatch behavior with void emit calls.

Warning impact:
- services/platform-service/src/modules/predictive-analytics/campaign-engine.ts: no-explicit-any 5 -> 0.
- Workspace lint baseline: 189 warnings -> 184 warnings.

Verification:
- pnpm --filter @lysnrai/platform-service build
- pnpm --filter @lysnrai/platform-service exec eslint src/modules/predictive-analytics/campaign-engine.ts
- pnpm --filter @lysnrai/platform-service test
- pnpm --filter @lysnrai/platform-service exec eslint . --ext .ts,.tsx
- pnpm lint
2026-05-04 15:58:44 -07:00
6978ddb209 chore(cowork-service): type test doubles
Replace cowork-service test any casts with structural test doubles for IPC bridges, Fastify request payloads, and private IPC bridge probes.

Verification: pnpm --filter @lysnrai/cowork-service build; pnpm --filter @lysnrai/cowork-service test; pnpm --filter @lysnrai/cowork-service exec eslint . --ext .ts,.tsx; pnpm lint.
2026-05-04 15:25:43 -07:00
9625999ad4 chore(platform-service): remove stale lint disables
Drop unused eslint-disable comments now that the ignored destructured names use the underscore convention.

Verification: pnpm --filter @lysnrai/platform-service build; pnpm --filter @lysnrai/platform-service exec vitest run src/lib/declarative-loader.test.ts --pool forks; pnpm --filter @lysnrai/platform-service exec eslint src/lib/declarative-loader.test.ts --ext .ts,.tsx; pnpm lint.
2026-05-04 15:22:37 -07:00
saravanakumardb1
7d266bfcc0 fix(docker): INFRA-gap-02 unblock full-stack docker compose up
Three coordinated fixes so 'docker compose up cosmos-emulator platform-service
cowork-service --wait' completes end-to-end (pre-existing blocker surfaced by
W1 post-push review).

1. Remove harmful prepare:tsc from @bytelyst/react-native-platform-sdk
   package.json. The hook fires during pnpm install --frozen-lockfile against
   an empty src/ tree (because Dockerfiles COPY package.jsons before
   sources), tsc aborts, install fails. Canonical monorepo build flow is
   pnpm -r build using the existing build:tsc script; prepare only runs for
   git+ URL installs (which this published package doesn't use), so removing
   it is lossless.

2. Add --ignore-scripts to platform-service + mcp-server Dockerfile install
   steps. Mirrors the pattern already used by extraction-service/Dockerfile,
   dashboards/admin-web/Dockerfile, dashboards/tracker-web/Dockerfile.
   Belt-and-braces against future prepare-hook regressions in any workspace
   package.

3. Expand .dockerignore node_modules/dist/.next/coverage to **/ globs.
   Docker's .dockerignore with bare 'node_modules' only matches root-level;
   nested packages/*/node_modules/ were being COPY'd into images, poisoning
   them with host-absolute-path .bin shims (e.g. @bytelyst/storage's tsc
   shim resolved to /learning_voice_ai_agent/node_modules/.pnpm/... which
   doesn't exist in the container → MODULE_NOT_FOUND). The glob fix makes
   COPY packages/ packages/ deliver source only.

Gap: INFRA-gap-02
Verified:
  pnpm install --frozen-lockfile                              
  pnpm --filter @bytelyst/react-native-platform-sdk build     
  pnpm --filter @bytelyst/react-native-platform-sdk typecheck 
  docker compose build platform-service                        (previously failed)
  docker compose build mcp-server                             
  docker compose build extraction-service                     
2026-04-16 15:48:32 -07:00
saravanakumardb1
dda74c2d20 feat(cowork-service): POST /api/plugins/reload
Hot-reload the orchestrator's on-disk plugin registry without a
restart. Routes to the reload_plugins Rust IPC method, gated by the
same authz the orchestrator enforces (admin role OR platform-signed
JWT) so a forbidden caller gets a canonical ForbiddenError envelope
instead of a raw IPC error passthrough. The response body is a
ReloadStats { loaded, added, removed, updated, errors } summary,
validated against ReloadResponseSchema before being returned to the
caller.

Tests cover: admin success (200 + envelope), user-without-platform
(403 before IPC), bridge unavailable (400), orchestrator -32003 →
ForbiddenError, other IPC errors → BadRequestError, malformed
orchestrator payloads → BadRequestError.

Phase: 3.1
Verified: pnpm -r typecheck, pnpm --filter @lysnrai/cowork-service {lint,build,test}
(140 passed, 6 new reload tests)
2026-04-16 15:45:42 -07:00
saravanakumardb1
b92aee729f feat(docker): INFRA-gap-01 wire cowork-service into compose stack
Adds cowork-service (port 4009) to docker-compose.yml with healthcheck,
depends_on gates for cosmos-emulator and platform-service, env_file
integration, and Traefik labels. Unblocks Phase 3 ecosystem wiring of
the ByteLyst roadmap.

Also adds the services/cowork-service/Dockerfile that compose builds
from. Pattern mirrors services/mcp-server/Dockerfile but copies the
full workspace in one step rather than enumerating every package.json,
to stay resilient to workspace membership changes. Production stage
runs `node dist/server.js` on :4009 with BusyBox-wget healthcheck
(bundled with node:22-alpine — no apk install required).

.env.example gains a Cowork-Service section documenting:
- ANTHROPIC_API_KEY, RUST_RUNTIME_BIN, RUST_RUNTIME_TIMEOUT_MS
- OLLAMA_URL, OLLAMA_MODELS
- FEATURE_FLAGS_ENABLED
The 13th clawcowork flag telemetry_enabled already ships via COMMON_FLAGS
in services/platform-service/src/modules/flags/seed.ts so seed.ts was not
touched.

Gap: INFRA-gap-01
Verified: docker compose config (YAML validity + env substitution),
          pnpm -r typecheck / lint / build / test (all green),
          docker compose build cowork-service (image built),
          docker compose up -d cowork-service --no-deps --wait (Healthy),
          curl -fsS localhost:4009/health → {"status":"ok","service":"cowork-service",...}.

Note: full-stack `docker compose up cosmos-emulator platform-service
cowork-service --wait` is blocked by a pre-existing issue in
services/platform-service/Dockerfile (react-native-platform-sdk prepare
script fails during pnpm install --frozen-lockfile in the image build).
That is outside W1 scope; cowork-service starts clean on its own and
becomes Healthy when platform-service is available out-of-band.
2026-04-16 13:07:11 -07:00
saravanakumardb1
a954f434ef fix(lint): repair pre-existing baseline lint errors blocking W1 gates
Baseline origin/main pnpm -r lint failed with 90+ errors across
platform-service, extraction-service, and tracker-web. These block the
shared W1 quality gates (prompts/README.md §4) which require all of
typecheck + lint + build + test to be green before committing W1 infra
work. Fixes are strictly scoped to unblock gates:

- eslint.config.js: extend @typescript-eslint/no-unused-vars with
  varsIgnorePattern / caughtErrorsIgnorePattern / destructuredArrayIgnorePattern
  all honouring the existing `^_` convention already used for args.
- platform-service: add file-level eslint-disable for
  @typescript-eslint/no-unused-vars, no-redeclare, no-useless-escape on
  the 33 legacy files failing lint (ab-testing, ai-diagnostics,
  diagnostics, predictive-analytics, broadcasts/types, surveys/types,
  lib/push-notifications).
- extraction-service tests: drop unused vitest imports (beforeEach,
  afterEach, HealthCheck).
- tracker-web tracker-proxy.test.ts: prefix unused url with _.
- Applied eslint --fix on platform-service which normalised a handful
  of `let` → `const` and removed one redundant disable comment.

Scope creep vs W1 "Files You Own" is acknowledged — user explicitly
approved this path when baseline rot was surfaced.

Verified: pnpm -r typecheck, lint, build, test all green.
2026-04-16 13:06:37 -07:00
saravanakumardb1
031e910607 fix(extraction-service): review fixes — locale mapping, model passthrough, content-type validation
BUG 1: Azure locale derivation produced 'en-EN' (invalid) for 2-letter codes.
  → Added toAzureLocale() with 28-language mapping table (en→en-US, pt→pt-BR, etc.)
  → Exported for testing; falls back to code-CODE for unmapped languages.

BUG 2: model field from request schema was silently dropped after provider refactor.
  → Added optional model field to TranscriptionInput interface.
  → OpenAI provider now uses input.model override (falls back to config.model).
  → Route passes model through to provider.transcribe().

GAP 4: SUPPORTED_AUDIO_TYPES was defined but never validated against.
  → Route now rejects unsupported content-types with a clear error message.
  → Allows application/octet-stream (Azure Blob SAS URLs often return this).

GAP 5: Client JSDoc still said 'via OpenAI Whisper API' — now 'via configured STT provider'.

GAP 8: Azure WAV content-type hardcoded samplerate=16000 — now generic audio/wav.

Tests: 42 transcription tests (was 35), 178 total passing.
  → toAzureLocale: 4 tests (locale mapping, passthrough, fallback, case-insensitive)
  → setSTT: 1 test (singleton override)
  → model passthrough: 2 tests (mock ignores, input accepts)
2026-04-06 11:40:27 -07:00
saravanakumardb1
a77b3ff931 refactor(extraction-service): provider-agnostic transcription — OpenAI + Azure Speech + Mock
- TranscriptionProvider interface with transcribe() + isConfigured()
- OpenAITranscriptionProvider: Whisper API (existing behavior)
- AzureTranscriptionProvider: Azure Speech REST API for short audio
- MockTranscriptionProvider: deterministic results for testing
- Factory: getSTT() singleton with env-driven auto-detection
  - STT_PROVIDER=openai|azure|mock (explicit)
  - Auto-detect: AZURE_SPEECH_KEY → azure, OPENAI_API_KEY → openai, else mock
- Config: add STT_PROVIDER, AZURE_SPEECH_KEY, AZURE_SPEECH_REGION env vars
- Route refactored: audio download (common) → provider.transcribe() (swappable)
- deriveFilename() extracted to types.ts (shared by route + providers)
- 35 transcription tests (was 12), 171 total passing
- Follows same pattern as @bytelyst/llm provider abstraction
2026-04-06 11:30:22 -07:00
saravanakumardb1
cc3fbf8187 feat(extraction-service): add /api/transcribe route — speech-to-text via OpenAI Whisper API
- POST /api/transcribe: download audio from URL, call Whisper API, return transcript
- Types: TranscribeRequestSchema (Zod), TranscribeResponse, SUPPORTED_AUDIO_TYPES
- Guards: 25MB size limit, 30s download timeout, 120s Whisper timeout, 429 rate limit
- Config: OPENAI_API_KEY, OPENAI_BASE_URL, WHISPER_MODEL env vars
- 12 new tests (schema validation + constants)
- Registered in server.ts alongside extract + task routes
2026-04-06 11:10:57 -07:00
saravanakumardb1
05594a334f feat(jobs): register devintelli-daily-sync cron job (0 6 * * *)
- Add devintelli-daily-sync handler: POST to DevIntelli backend /api/sync/daily
- Uses x-internal-key header for service-to-service auth
- Add DEVINTELLI_BACKEND_URL + DEVINTELLI_INTERNAL_API_KEY env vars
- Cron: 0 6 * * * (6am UTC daily), timeout: 5 min
- Returns triggered/skipped/totalConnections metrics from DevIntelli response
2026-04-04 23:37:25 -07:00
saravanakumardb1
89e200fa9f feat(flags): seed devintelli feature flags (11 flags)
- devintelli_enabled, devintelli_scan_enabled, devintelli_daily_sync
- 6 analytics panel flags (overview, commit, pr, review, language, productivity, repo)
- devintelli_billing_enabled (disabled by default)

Aligns with backend/src/lib/feature-flags.ts defaults
2026-04-04 23:37:25 -07:00
82a44c249f feat(runtime): add Cowork checkpoint drill-in 2026-04-04 17:29:12 -07:00
59ae0e1943 feat(runtime): add checkpoint artifact id contract 2026-04-04 14:27:26 -07:00
32b46f0625 feat(cowork-service): map enriched checkpoint refs and IPC ids 2026-04-04 13:51:57 -07:00
9aeb9bbd59 feat(runtime): add checkpoint summaries to shared and cowork surfaces 2026-04-04 12:13:46 -07:00
97b731e14f feat(cowork-service): add runtime todo projection 2026-04-04 11:32:46 -07:00
fdf9286e34 fix(audit): preserve source event timestamps 2026-04-04 11:27:21 -07:00
a57b367fe5 feat(cowork-service): prefer canonical audit event ids 2026-04-04 11:19:25 -07:00
ff8c5eb704 fix(runtime): add queued agent run state 2026-04-04 11:11:45 -07:00
b8242b4601 feat(cowork-service): add runtime action log projection 2026-04-04 02:20:19 -07:00
01201f8f56 feat(cowork-service): add runtime task projection 2026-04-04 02:18:47 -07:00
023826e413 feat(cowork-service): add runtime projection routes 2026-04-04 01:52:04 -07:00
fe36296196 feat(runtime): add platform runtime projection api 2026-04-04 01:14:37 -07:00
e377351842 feat(timeline): add platform timeline ingest and query api 2026-04-04 00:54:07 -07:00
705f58c5c5 chore(deploy): remove railway deployment artifacts 2026-04-03 17:05:15 -07:00
6936c007c7 fix(cowork-service): preserve budget policy auth errors 2026-04-03 14:09:52 -07:00
6c2e9a67ca test(cowork-service): skip integration suite without credentials 2026-04-03 13:58:28 -07:00
5c08832a3e feat(cowork-service): H.9 push notification stubs 2026-04-03 13:55:10 -07:00
2f8fe13c43 test(cowork-service): ecosystem integration tests (H.1-H.12) 2026-04-03 13:53:29 -07:00
a7468eaa3f feat(cowork-service): add budget policy proxy routes 2026-04-03 13:48:52 -07:00
be2f29d1b8 feat(cowork-service): add deferred IPC modules 2026-04-03 13:44:13 -07:00
saravanakumardb1
2d70eeeeb0 fix(cowork-service): audit fixes — JWT auth forwarding + temperature:0 falsy bug
Marketplace proxy:
- Forward Authorization header to platform-service for consumer/author
  routes that call requireAuth() — without this, all authenticated
  marketplace endpoints would 401
- Add 2 tests: auth header forwarding + omission when absent
  (100 tests, was 98)

IPC intercept_llm handler:
- Replace || with ?? for temperature and max_tokens — temperature:0
  is a valid value (deterministic) but || treated it as falsy, passing
  undefined to the LLM router instead
2026-04-03 01:32:34 -07:00
saravanakumardb1
bba26f2d5f feat(cowork-service): H.12 marketplace proxy — migrate TO platform marketplace
Add marketplace module that proxies all requests to platform-service's
marketplace module. Replaces the local plugin marketplace (Phase 10)
with the shared ByteLyst platform marketplace.

Endpoints proxied (18 routes):
  Public: browse catalog, listing detail, reviews, featured, categories
  Consumer: install/uninstall, my installs, add review, vote toggle
  Author: create/update/delete listings, my listings, submit, publish

Changes:
- modules/marketplace/types.ts: Zod schemas for query validation
- modules/marketplace/routes.ts: 18 proxy routes with proxyGet/proxyMutate
  helpers, productId injection, x-request-id forwarding
- modules/marketplace/routes.test.ts: 13 tests (public, consumer, author,
  error handling, 502 fallback, query validation)
- server.ts: Register marketplaceRoutes (8th module), fix costUsd type cast
- server.test.ts: Add marketplace mock, update register count 7→8

Test count: 98 (was 85)
2026-04-03 01:26:30 -07:00
saravanakumardb1
d838cd658b feat(cowork-service): IPC LLM interception — Rust runtime delegates LLM calls to multi-provider router
Add reverse-IPC protocol support: Rust runtime can send intercept_llm
requests to cowork-service, which routes them through @bytelyst/llm-router.

Changes:
- ipc-bridge.ts: handleLine now detects incoming requests (has 'method' field)
  vs normal responses. New handleIncoming() + sendResponse() for reverse IPC.
  New onIncomingRequest() to register the handler.
- server.ts: Wires intercept_llm handler — validates messages, calls
  getLlmRouter().chat(), records spend for budget tracking, logs provider/model.
- ipc-bridge.test.ts: 5 new tests for reverse IPC (handler registration,
  routing, error handling, request vs response disambiguation).
- server.test.ts: Updated IPC bridge mock with onIncomingRequest.

Test count: 85 (was 80)
2026-04-03 01:11:34 -07:00
saravanakumardb1
a9d4c63e03 fix(cowork-service): audit proxy missing taskId and tool query param forwarding
AuditQuerySchema now accepts taskId and tool optional fields.
Route forwards them as query params to platform-service GET /audit.
Previously these filters sent by the frontend were silently stripped.
2026-04-03 01:05:56 -07:00
saravanakumardb1
8e12409938 test(cowork-service): integration tests for proxy routes — 80 tests passing
Add test files for all 4 new proxy route modules:
- audit/routes.test.ts (5 tests): query, stats, 502 fallback, non-ok forward
- usage/routes.test.ts (5 tests): summary, check-limits, 502 fallback, non-ok forward
- notifications/routes.test.ts (8 tests): prefs get/put, webhooks CRUD, 502 fallback
- extraction/routes.test.ts (5 tests): extract, models, 502 fallback, non-ok forward

All tests use mocked fetch to verify proxy behavior without real services.
80 tests passing (13 test files), typecheck clean.
2026-04-03 00:13:13 -07:00
saravanakumardb1
62997bb1db feat(cowork-service): H.10 extraction proxy routes + EXTRACTION_SERVICE_URL config
Add extraction proxy routes to cowork-service for hybrid document processing:
- POST /api/extract — proxy to extraction-service POST /extract
- GET /api/extract/models — list available extraction models
- modules/extraction/routes.ts — proxy routes with error handling
- lib/config.ts — add EXTRACTION_SERVICE_URL (default: http://localhost:4005)
- server.ts — register extractionRoutes (7 route modules total)
- server.test.ts — add extraction routes mock, update register count to 7

Hybrid approach: Rust skills server handles local doc processing (PDF/xlsx/docx/pptx)
inside Docker sandbox, extraction-service provides AI-powered entity extraction.

57 tests passing, 9 test files, typecheck clean
2026-04-03 00:04:11 -07:00
saravanakumardb1
88cc18549c feat(cowork-service): H.9 notification + webhook proxy routes
Add notification and webhook management routes to cowork-service:
- GET /api/notifications/prefs — get user notification preferences
- PUT /api/notifications/prefs — update user notification preferences
- GET /api/webhooks — list webhook subscriptions
- POST /api/webhooks — create webhook subscription
- DELETE /api/webhooks/:id — delete webhook subscription
- modules/notifications/routes.ts — proxy routes with error handling
- server.ts — register notificationRoutes (6 route modules total)
- server.test.ts — add notification routes mock, update register count to 6

57 tests passing, 9 test files, typecheck clean
2026-04-03 00:00:14 -07:00
saravanakumardb1
cd5483c95b feat(cowork-service): H.6 usage/budget proxy routes
Add usage query routes to cowork-service that proxy to platform-service:
- GET /api/usage/summary — user's aggregated usage with days filter
- POST /api/usage/check-limits — check if user is within plan limits
- modules/usage/types.ts — UsageSummaryQuerySchema, CheckLimitsSchema (Zod)
- modules/usage/routes.ts — proxy routes with error handling
- server.ts — register usageRoutes (5 route modules total)
- server.test.ts — add usage routes mock, update register count to 5

57 tests passing, 9 test files, typecheck clean
2026-04-02 23:58:14 -07:00
saravanakumardb1
dc27ee9f21 feat(cowork-service): H.5 audit proxy routes — dual-source audit queries
Add audit query routes to cowork-service that proxy to platform-service:
- GET /api/audit — query audit logs with action/category/days/limit/offset filters
- GET /api/audit/stats — aggregated audit stats
- modules/audit/types.ts — AuditQuerySchema (Zod)
- modules/audit/routes.ts — proxy routes with error handling
- server.ts — register auditRoutes
- server.test.ts — add audit routes mock, update register count to 4

57 tests passing, 9 test files, typecheck clean
2026-04-02 23:54:42 -07:00
saravanakumardb1
ca7c3e571e fix(cowork-service): audit H.7 — fix LLM timeout, harden test mocks, add Ollama config
Bug fixes from systematic review of H.7 LLM router wiring:
- lib/llm-router.ts: remove RUST_RUNTIME_TIMEOUT_MS (300s IPC timeout) override
  — let LlmRouter use its built-in 30s default, appropriate for cloud API calls
- server.test.ts: add debug/error to appMock.log — prevents fragile failures
  if any startup path hits those log levels
- server.test.ts: add OLLAMA_URL + OLLAMA_MODELS to config mock

New feature:
- config.ts: add OLLAMA_URL + OLLAMA_MODELS env vars for local Ollama support
- server.ts: wire Ollama env vars into initLlmRouter() — set
  OLLAMA_MODELS=model1,model2 to auto-add local Ollama as a provider

57 tests passing, 9 test files, typecheck clean
2026-04-02 23:37:50 -07:00
saravanakumardb1
f542160784 feat(cowork-service): H.7 — wire @bytelyst/llm-router for multi-model routing
Added LLM routing module to cowork-service:
- lib/llm-router.ts — singleton LlmRouter with cloud + local Ollama support
- modules/llm/types.ts — Zod request schemas
- modules/llm/routes.ts — POST /api/llm/chat, GET /api/llm/providers, GET /api/llm/health
- All endpoints gated by llm_multi_model_enabled feature flag
- Best-effort init: service works without API keys (router stays uninitialized)
- 8 new tests (routes), server test updated for 3 route modules
- 57 total tests passing, typecheck clean
2026-04-02 23:10:07 -07:00
saravanakumardb1
53c3565874 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.
2026-04-02 23:02:38 -07:00
saravanakumardb1
9fc5af5b2b test(cowork-service): platform-client + flush-scheduler tests (17 new tests)
New test files:
- lib/platform-client.test.ts (8 tests): audit posting, telemetry batch,
  usage records, flag polling, error handling, query params
- lib/flush-scheduler.test.ts (9 tests): lifecycle start/stop, flushAll with
  IPC drain → platform-service posting, IPC error handling, empty responses,
  pollAndSyncFlags with local registry + IPC update, failure graceful handling

49 tests passing (was 32), 8 test files, typecheck clean.
2026-04-02 22:53:04 -07:00
saravanakumardb1
f8f3cdc242 feat(cowork-service): platform-client + flush scheduler (H.4-H.8 TS wiring)
New files:
- lib/platform-client.ts — REST client for platform-service endpoints:
  POST /audit, POST /telemetry/events, POST /usage, GET /flags/poll

- lib/flush-scheduler.ts — periodic drain of IPC buffers → platform-service:
  - flushAll(): drains audit, telemetry, budget from Rust IPC → REST
  - pollAndSyncFlags(): GET /flags/poll → update TS registry + push to IPC
  - Singleton pattern with start/stop/finalFlush lifecycle
  - All operations best-effort (logged, never crash service)

Updated server.ts:
- Starts flush scheduler after IPC bridge connects
- finalFlush() before shutdown (drain remaining events)

32 tests passing, typecheck clean.
2026-04-02 22:50:00 -07:00
saravanakumardb1
ff433e172d test(cowork-service): add product-config, feature-flags, health routes tests
New test files (3):
- lib/product-config.test.ts — 3 tests: PRODUCT_ID, productConfig fields, consistency
- lib/feature-flags.test.ts — 3 tests: 13 flag names match seed.ts, defaults correct, setFlag override
- modules/health/routes.test.ts — 2 tests: degraded when IPC disconnected, connected status reporting

32 tests passing (was 24), 6 test files, typecheck clean.
2026-04-02 22:22:59 -07:00
saravanakumardb1
2191427605 fix(cowork-service): 3 bugs — flag names, IPC call guard, health status
BUG 1: feature-flags.ts had 3 wrong flag names + missing 3 from seed.ts
  - Removed: browser_extension_enabled, institutional_knowledge_enabled
  - Renamed: connectors_enabled → mcp_connectors_enabled
  - Added: llm_multi_model_enabled, telemetry_enabled, platform_auth_required
  - Fixed defaults to match seed.ts (marketplace_enabled=true, dispatch_api_enabled=true)
  - Now 13 flags exactly matching platform-service/src/modules/flags/seed.ts

BUG 2: ipc-bridge.ts call() had 'initialize' exemption that allowed null deref
  - If call('initialize') was invoked externally without start(), the guard
    passed but this.child!.stdin!.write() would crash with null dereference
  - During normal start(), child.stdin.writable is true so no exemption needed
  - Removed the method !== 'initialize' exemption

BUG 3: health routes didn't factor IPC bridge into overall health status
  - allOk only checked platform-service reachability
  - Now allOk = depsOk && ipcConnected — service reports 503 when bridge is down
  - IPC bridge disconnection makes health 'degraded' (correct — fallback mode works)

24 tests passing, typecheck clean.
2026-04-02 22:20:52 -07:00
saravanakumardb1
19674c7ef7 feat(cowork-service): ecosystem alignment + IPC bridge to Rust runtime
ECOSYSTEM GAPS CLOSED — cowork-service now matches the pattern used by
all other product backends (FlowMonk, ActionTrail, NoteLett, etc.):

New lib files (6):
- lib/product-config.ts — canonical product identity (PRODUCT_ID, productConfig)
- lib/auth.ts — @bytelyst/fastify-auth createAuthMiddleware
- lib/request-context.ts — getUserId(), getRequestProductId()
- lib/telemetry.ts — @bytelyst/backend-telemetry buffer
- lib/feature-flags.ts — @bytelyst/backend-flags with 12 cowork flags
- lib/ipc-bridge.ts — IpcBridge class: spawn Rust child, JSON-RPC, 13 methods

Updated files:
- lib/config.ts — extends @bytelyst/backend-config baseBackendConfigSchema
- server.ts — JWT context, bootstrap endpoint, IPC startup, graceful shutdown
- modules/tasks/routes.ts — IPC bridge forwarding with in-memory fallback
- modules/health/routes.ts — productId from product-config, IPC status
- package.json — 7 new @bytelyst/* workspace deps

IPC bridge features:
- Spawns cowork-orchestrator --ipc-bridge as child process
- JSON-RPC 2.0 over stdin/stdout (line-delimited)
- 13 convenience methods matching Rust IpcHandler
- Timeout + pending request tracking
- Graceful shutdown with SIGTERM
- Singleton pattern with setIpcBridge() for testing

24 tests passing (was 8), typecheck clean.
2026-04-02 22:14:24 -07:00
saravanakumardb1
a87c533fd3 feat(cowork-service): scaffold Fastify bridge + seed clawcowork feature flags (H.1 + H.2)
H.1: Product registration
- Added 12 clawcowork feature flags to platform-service flags/seed.ts
  (sandbox, plugins, mcp, scheduling, computer_use, parallel_agents,
   marketplace, wasm, llm_multi_model, audit, platform_auth, dispatch_api)

H.2: cowork-service scaffold (services/cowork-service/)
- @lysnrai/cowork-service on port 4009, productId clawcowork
- createServiceApp + startService from @bytelyst/fastify-core
- Modules: health (dependency check), tasks (submit/list/get/cancel)
- Zod-validated config, Swagger, readiness endpoint
- 8 tests passing (1 bootstrap + 7 task routes), typecheck clean
2026-04-02 20:39:22 -07:00
saravanakumardb1
af605a6e7d fix(mcp): align ChronoMind type enums with actual backend schema
Fix 3 type mismatches in MCP chronomind-client.ts + chronomind-tools.ts:

1. TimerDoc.type: Remove non-existent 'event', keep 'countdown'|'alarm'|'pomodoro'
2. TimerDoc.state: Remove non-existent 'idle', add missing 'snoozed'|'dismissed'
3. RoutineDoc.status: Replace wrong 'idle'|'running' with actual
   'template'|'ready'|'active'|'cancelled'

Fix cascading usages:
- chronomind.timers.create tool: default state 'idle' → 'active'
- chronomind.timers.list tool: update type/state enum in Zod schema + description
- calendar-import-pipeline.ts: 'idle' → 'active' for imported timers

MCP server typecheck passes. No runtime behavior change for existing tools.
2026-03-31 23:57:24 -07:00
saravanakumardb1
efde14ba6e feat(mcp): Phase A.3 — 5 new ChronoMind MCP tools + client functions
Extend centralized MCP server with 5 new ChronoMind tools:

- chronomind.timers.reschedule — shift timer by delta or set new target time
- chronomind.timers.availability — find free time slots in a window
- chronomind.routines.start — start a routine from ready/template status
- chronomind.agentActions.list — list agent action audit trail
- chronomind.agentActions.approve — approve a proposed agent action

Client functions added to chronomind-client.ts:
- chronomindTimerReschedule, chronomindTimerAvailability, chronomindRoutineStart
- chronomindAgentActionCreate, chronomindAgentActionsList, chronomindAgentActionApprove

Write tools (reschedule, routines.start) record agent actions for audit trail.
Audit recording is fail-open — failures don't block the actual operation.

MCP server typecheck passes. No breaking changes to existing tools.
2026-03-31 23:41:43 -07:00
root
81951b173a feat(extraction): back product rate limits with valkey 2026-03-31 08:08:53 +00:00
root
b8661392c6 feat(observability): add phase 2 monitoring and valkey services 2026-03-31 06:57:12 +00:00
58c47a751a fix(mcp-server): pass workspaceId to notelett note get/update/delete/summarize tools
Backend requires workspaceId query param on single-note endpoints.
Updated client functions and tool schemas accordingly.

Made-with: Cursor
2026-03-29 22:10:03 -07:00
6997dff8d9 feat(mcp-server): register NoteLett tools (notes, workspaces, tasks, artifacts, summarize)
Adds notelett-client.ts HTTP wrapper, notelett-tools.ts with 10 MCP tool registrations,
and NOTELETT_BACKEND_URL config entry.

Made-with: Cursor
2026-03-29 20:57:16 -07:00
root
eba6c7a641 chore(platform): align docker and package outputs 2026-03-29 23:41:08 +00:00
saravanakumardb1
46ee14371c fix(ci): add --pool forks to all vitest test scripts to fix kill EPERM on Node v25
Root cause: tinypool worker teardown calls kill() which returns EPERM
in the act_runner host environment on Node.js v25.2.1. Tests pass but
the vitest process crashes during cleanup, causing CI failure.

Fix: --pool forks CLI flag on every package/service test script, plus
pool: 'forks' in all vitest.config.ts files. This uses child_process.fork()
worker management which handles termination cleanly.

60 package.json files updated, 10 vitest.config.ts files updated.
2026-03-27 23:23:38 -07:00
saravanakumardb1
0628f5b3bf test(platform): add 4 impersonation business rule tests (6→10) 2026-03-27 13:22:12 -07:00
saravanakumardb1
3cda7190fb feat(platform): add i18n translations module (P3.20) 2026-03-27 11:32:39 -07:00
saravanakumardb1
85aca5534b fix(docker): sync all 3 service Dockerfiles with complete workspace package.json list
platform-service had 16/60, extraction-service had 14/60, mcp-server had 34/60.
All three now list all 57 packages + 4 services + 2 dashboards + scripts.
Required for pnpm install --frozen-lockfile to resolve the full workspace.
2026-03-24 11:55:47 -07:00
saravanakumardb1
59f6ac1b9a fix(ai-diagnostics): keep cluster filters numeric 2026-03-23 16:21:08 -07:00
saravanakumardb1
cd811114e5 fix(devops): harden local shared-service docker bring-up 2026-03-22 12:34:38 -07:00
saravanakumardb1
67ef6a6068 fix(exports): preserve processing state on async export failures 2026-03-22 11:58:54 -07:00
saravanakumardb1
265599d005 fix(platform-service): harden broadcast metrics and export job lifecycle 2026-03-22 11:57:47 -07:00
saravanakumardb1
dda38aa009 fix(exports): strip data payload from list endpoint + update audit doc
- exports/routes: exclude inline data from GET /exports list response
  to prevent returning megabytes of serialized export data (perf+security)
- Update WORKSPACE_TODO_AUDIT.md: add post-audit review section with
  9 bugs found and fixed across 2 commits (73b07c2, 841cdf3), mark
  all action plan sprints complete
- Typecheck clean, 1483/1483 tests pass
2026-03-22 01:23:08 -07:00
saravanakumardb1
841cdf3a16 fix(platform-service+events): 3 more gaps in diagnostics + delivery
- diagnostics/subscribers: wire session.created email notification to
  target user using existing 'diagnostics-session-created' template
  (was just logging instead of sending the email)
- events/types: add missing 'currency' field to payment.failed schema
  (payment.succeeded had it, payment.failed did not — inconsistency)
- delivery/subscribers: use event.payload.currency instead of hardcoded
  empty string in payment-failed email variables
- Typecheck clean, 1483/1483 tests pass
2026-03-22 01:20:24 -07:00
saravanakumardb1
73b07c2c3a fix(platform-service): 5 bugs in recent P2/P3 implementations
- diagnostics/subscribers: use correct template IDs
  'diagnostics-session-cancelled' and 'diagnostics-session-completed'
  instead of non-existent 'generic' (would throw at runtime)
- delivery/templates: add missing 'broadcast' email template used by
  broadcast delivery route (dispatchEmail would throw on unknown ID)
- broadcasts/routes: replace broken dot-path 'metrics.sent' update
  with proper updateBroadcastMetrics() call, add productName variable
- exports/routes: store serialized data on job doc, add download
  endpoint GET /exports/:id/download with content-type headers,
  exclude data payload from metadata GET endpoint
- waitlist/routes: store invitation doc ID (inv_...) instead of
  code string (WL-...) in invitationCodeId field
- delivery/delivery.test.ts: update template count 12 -> 13
- Typecheck clean, 1483/1483 tests pass
2026-03-22 01:14:55 -07:00
saravanakumardb1
1576b699b0 feat(platform-service): resolve all P3 TODOs — diagnostics notifications + test cleanup
- diagnostics/subscribers: notify admin via email when debug session is
  cancelled (looks up session creator via getSession + getUserById)
- diagnostics/subscribers: email session summary (logs/traces/screenshots)
  to admin when debug session completes
- diagnostics/subscribers: send Slack alert via dispatchSlack for FATAL
  logs ingested during debug sessions (on-call engineer notification)
- feedback-client/integration.test.ts: replace TODO-4 with clear NOTE,
  fix unused var lint errors
- feedback-client/gdpr.test.ts: mark lifecycle policy as accepted,
  remove console.log + unused blobPath variable
- Update WORKSPACE_TODO_AUDIT.md — P3 section: all 5 resolved
- Typecheck clean, 1483/1483 tests pass
2026-03-22 01:03:51 -07:00
saravanakumardb1
6f03a74a76 feat(platform-service): resolve P2 TODOs — exports, broadcasts, telemetry, waitlist
- telemetry/repository: group upsertEventsBatch by pk — same-partition
  writes sequential, different partitions parallel (reduces contention)
- exports/routes: wire async export processing via process.nextTick —
  queries users/audit/telemetry/usage/subscriptions/licenses, serializes
  to CSV or JSON, updates job status with rowCount and fileSizeBytes
- broadcasts/repository: replace mock estimateTargetReach with real user
  count query from auth module, respects percentageRollout
- broadcasts/routes: wire async broadcast delivery — fetches target users,
  dispatches email per recipient, updates metrics on completion
- waitlist/routes: auto-generate invitation codes via invitations module
  when batch-inviting waitlist entries (WL-XXXXXXXX format, 14-day trial)
- CAPTCHA (item 12) deferred — requires external API keys
- Update WORKSPACE_TODO_AUDIT.md — P2 section: 5/6 resolved
- Typecheck clean, 1483/1483 tests pass
2026-03-22 00:41:11 -07:00
saravanakumardb1
09525f671f fix(platform-service): 3 bugs in delivery subscribers + survey incentives
- delivery/subscribers: welcome email used raw productId as productName,
  now uses resolveProductName() for proper display name
- delivery/subscribers: remove redundant String(daysLeft) in trial_expiring
- surveys/routes: incentiveClaimed was set outside if(sub) block, marking
  response as claimed even when user has no subscription. Moved inside
  if(sub) so claims are only recorded when incentive is actually granted
2026-03-22 00:19:32 -07:00
saravanakumardb1
2f06aacc27 fix(platform-service): resolve P1 TODOs — delivery email subscribers + survey incentives
- delivery/subscribers: add resolveUserEmail() helper using auth getById()
- payment.failed: look up user email, dispatch payment-failed template
- trial_expiring: look up user, compute daysLeft from expiresAt, dispatch
- trial_expired: look up user, dispatch trial-expired template with upgradeUrl
- surveys/routes: wire incentive fulfillment to subscriptions module
  - pro_days: extend currentPeriodEnd by incentive amount
  - credits: add bonus tokensIncluded via subscriptions repo
- Update WORKSPACE_TODO_AUDIT.md — P0+P1 all resolved (7/18)
- Typecheck clean, 1483/1483 tests pass
2026-03-22 00:14:41 -07:00
saravanakumardb1
9180954903 fix(platform+admin-web): 3 bugs in delivery retry + webhooks delivery loading
Backend (delivery retry):
- Use NotFoundError (404) instead of BadRequestError (400) for missing log doc
- Add telegram + slack retry support (was email-only, threw error for others)

Frontend (delivery page):
- Add pk field to DeliveryEntry interface
- Pass pk query param in retry call so backend can look up the doc
- Fix handleRetry to accept full entry object instead of just id

Frontend (webhooks page):
- Parallelize delivery fetches with Promise.allSettled (was sequential for loop)
- Significant page load improvement for subscriptions with many deliveries
2026-03-21 23:21:58 -07:00
saravanakumardb1
ead9457345 feat(platform+admin-web): implement 4 missing backend endpoints + re-enable frontend
Backend endpoints added:
- POST /delivery/logs/:id/retry — re-dispatches failed email deliveries (Q1)
- POST /reviews/:id/flag — flags review item with reason + admin metadata (Q2)
- DELETE /agent-evals/suites/:id — deletes evaluation suite with 204 response (Q3)

Frontend re-enabled:
- delivery: retry button for failed entries
- reviews: flag dropdown menu item
- agent-evals: delete dropdown menu item + Trash2 icon

Frontend fixed:
- webhooks: per-subscription delivery loading via GET /subscriptions/:id/deliveries (Q4)
2026-03-21 23:11:38 -07:00
saravanakumardb1
d1d01727e4 fix(platform): register ai-diagnostics routes + wire 6 hidden sidebar pages
Phase 0 from DASHBOARD_UI_COVERAGE_ROADMAP:
- Register ai-diagnostics routes in server.ts (671-line module was never mounted)
- Add 6 hidden pages to admin sidebar-nav.tsx:
  Debug Sessions, Health Dashboard, Extraction, Experiments,
  Predictive, AI Diagnostics
- /users was already in sidebar (no change needed)
- Kill switch verified: already per-product via productId query param
- Admin sidebar now has 33 items (was 27)
2026-03-21 17:40:35 -07:00
saravanakumardb1
267f8af3a4 test(ai-diagnostics): add 94 tests for error-normalization, clustering, query-parser 2026-03-21 17:06:24 -07:00
saravanakumardb1
2c6397272f fix(test): add env defaults to platform-service vitest config
Aligns service-local vitest.config.ts with root config so tests pass
both via 'pnpm test' (uses service config) and 'npx vitest run' (uses root).
Fixes telemetry.test.ts which fails because its import chain eagerly
loads config.ts → envSchema.parse() requiring COSMOS_ENDPOINT/KEY/JWT_SECRET.

Added: RATE_LIMIT_STORE_MODE=memory, COSMOS_ENDPOINT, COSMOS_KEY, JWT_SECRET
(all test-safe placeholders, never used at runtime with DB_PROVIDER=memory)
2026-03-21 15:32:14 -07:00
saravanakumardb1
7613d6890f feat(field-encrypt): admin-panel encryption toggle via feature flags
- FieldEncryptorConfig.enabled: false returns NullFieldEncryptor (no-op)
- NullFieldEncryptor stores plaintext as-is, decrypt returns ct directly
- 7 new tests for toggle behavior (50/50 total)
- encryption_enabled added to COMMON_FLAGS (seeded for all 10 products)
2026-03-21 15:24:19 -07:00
saravanakumardb1
4a47db72ae fix(flags): SSE stream endpoint + client — pass productId via query string
EventSource API cannot set custom headers, so the SSE /flags/stream
endpoint and feature-flag-client were broken for streaming mode:
- Server: accept productId and token from query string as fallback
  when x-product-id / authorization headers are absent
- Client: pass productId (and optional auth token) as query params
  when constructing the EventSource URL
2026-03-21 12:12:14 -07:00
saravanakumardb1
1e1ee969dc feat(flags): add seed flags for 6 missing products + 6 new evaluator edge-case tests
- seed.ts: add default flags for jarvisjr (3), peakpulse (3), flowmonk (2), notelett (2), actiontrail (2), localmemgpt (2)
  Previously only chronomind, nomgap, mindlyst, smartauth, lysnrai had seed flags — common flags (maintenance_mode, telemetry_enabled) were not seeded for newer products
- flags.test.ts: 63 → 69 tests (+6):
  - anonymous user with partial percentage returns off
  - partial rule rollout (0%) skips even matching users
  - neq operator (not equal)
  - contains operator
  - gte + lt numeric range on custom attributes
  - missing context attribute returns off
2026-03-21 11:52:08 -07:00
saravanakumardb1
dd113b96c9 fix(flags): critical partition key bug + audit snapshot integrity + anonymous rollout
- repository.ts: update() and remove() now require productId as partition key
  (was passing 'id' as both params — works with memory provider but fails on Cosmos DB)
- repository.ts: updateSegment() and removeSegment() also fixed
- routes.ts: all repo.update/remove calls updated to pass productId
- routes.ts: audit 'before' snapshots now use JSON deep copy instead of shallow spread
  (prevents nested object mutation from corrupting audit trail)
- routes.ts: kill switch audit now uses repo.update() return value for 'after' snapshot
- evaluator.ts: anonymous users (no userId) with partial percentage (0 < pct < 100)
  now correctly return 'off' instead of falling through to default variation
  (can't deterministically hash without a userId)
2026-03-21 11:50:08 -07:00
saravanakumardb1
ca6a4d41d8 feat(flags): production-grade feature flag system — multi-variate, segments, audit, SSE, scheduling, prerequisites
- types.ts: multi-variate flags (boolean/string/number/JSON), targeting rules with 18 operators, scheduling (enableAt/disableAt/gradual rollout), prerequisites, segments, audit log, evaluation context
- evaluator.ts: pure evaluation engine — schedule checking, prerequisite dependencies (circular detection), individual targeting, targeting rules (AND clauses), segment matching, percentage rollout (FNV-1a), OS version/platform/region filtering
- repository.ts: 3 collections — feature_flags, flag_segments, flag_audit_log
- routes.ts: 18 endpoints — flag CRUD, toggle, archive, kill switch (with tag filter), segment CRUD, audit log, POST /flags/evaluate (multi-variate), SSE /flags/stream, legacy /flags/poll backward-compat
- seed.ts: updated to produce full FeatureFlagDoc with variations, version
- flags.test.ts: 63 tests — schema validation, evaluator engine, targeting rules, segments, prerequisites, scheduling, gradual rollouts, multi-variate, version comparison, deterministic hashing
- @bytelyst/events: added flag.created, flag.updated, flag.deleted, flag.kill_switch event types
- @bytelyst/feature-flag-client: multi-variate support (getValue, getEvaluation, getAllEvaluations), SSE streaming mode, onChange listeners, auth token injection
- event-dispatcher.ts + webhooks/types.ts: wired new flag events
2026-03-21 11:44:49 -07:00
saravanakumardb1
26283b402a test(platform-service): cover ai diagnostics routes 2026-03-21 10:45:41 -07:00
saravanakumardb1
10c288857d fix(support-cases): prevent auto-triage from regressing case status
- Auto-triage previously always set status to 'triaged', even for cases
  already in in_progress, escalated, or other later states
- Now only transitions to 'triaged' if case is still in 'open' state
- Cases in later states keep their current status (only priority + tags update)
- Added regression test for in_progress case
- 10 support-cases tests passing
2026-03-20 06:25:43 -07:00
saravanakumardb1
78cb958a6d fix(ai-budgets): tighten rollover period filter to exclude stale entries
- Previous filter only checked e.recordedAt < currentPeriodStart
- Now also checks e.recordedAt >= prevPeriodStart (lower bound)
- Prevents entries from periods before the previous one from inflating
  the spent amount, which would reduce the rollover incorrectly
- 12 ai-budgets tests passing
2026-03-20 06:24:13 -07:00
saravanakumardb1
f3a4d915f5 fix(support-cases): prevent crash when auto-triage encounters undefined tags
- supportCase.tags is optional in SupportCaseDoc schema
- Spreading undefined throws TypeError at runtime
- Fixed both [...supportCase.tags] and .includes() call with ?? [] fallback
- Added regression test for undefined tags case
- 9 support-cases tests passing
2026-03-20 06:23:34 -07:00
saravanakumardb1
0bbae1f14e feat(platform): Phase 6 — Support Case Management
- Case timeline: GET /support/cases/:id/timeline
  - Merges case creation, notes, escalations chronologically
- SLA engine: GET /support/cases/:id/sla
  - Priority-based SLA targets (critical=1h/4h, high=4h/24h, etc.)
  - First-response and resolution breach detection
- Auto-triage: POST /support/cases/:id/auto-triage
  - Keyword-based priority heuristics (outage→critical, error→high, etc.)
  - Category detection (auth, billing, api)
  - Deduped tag application
- Case metrics: GET /support/metrics
  - Aggregates by status/priority/source
  - Avg resolution hours, SLA breach count, compliance rate
- New repo function: listAllCases
- 1,336 tests passing (5 new)
2026-03-20 03:38:08 -07:00
saravanakumardb1
a060ee4496 feat(platform): Phase 5 — Human Review Queue
- Batch decisions: POST /reviews/batch-decision (up to 50 items)
  - Parallel execution with allSettled, reports succeeded/failed counts
- Delegation: POST /reviews/:id/delegate
  - Reassigns review with delegation metadata tracking
  - Triggers notification to new assignee
- Auto-expiry: POST /reviews/expire
  - Scans pending/assigned reviews past dueAt, marks expired
- Review stats: GET /reviews/stats
  - Aggregates by status/priority/category, avg resolution time
  - Computes pendingCount, overdueCount, avgResolutionHours
- New repo functions: listExpired, listAll
- 1,331 tests passing (7 new)
2026-03-20 03:33:55 -07:00
saravanakumardb1
9758192377 feat(platform): Phase 4 — AI Governance & Evals
- Run history: GET /agent-evals/suites/:id/runs with limit param
- Regression comparison: GET /agent-evals/suites/:id/regression
  - Detects 5%+ score drop between consecutive runs
  - Returns latest vs previous comparison + trend data
- Release gate check: GET /agent-evals/suites/:id/gate
  - Checks if latest release-gate run passed threshold
- Agent compliance report: GET /agent-evals/agents/:agentId/report
  - Aggregates pass rate, avg score, suite counts, recent runs
- Eval scheduling: POST /agent-evals/suites/:id/schedule
  - Wires eval suite to job runner with cron expression
- New repo functions: listRunsBySuite, listRunsByAgent
- 1,324 tests passing (8 new)
2026-03-20 03:30:03 -07:00
saravanakumardb1
05acacd400 feat(platform): Phase 3 — AI Budget & Cost Governance
- Scope expansion: BudgetScopeTypeSchema now includes 'org' + 'workspace'
- Cost dashboard: GET /ai-budgets/costs with groupBy (model/agent/day/scope)
  - Aggregates totalCostUsd, totalTokens, entryCount, breakdown
- Budget rollover: POST /ai-budgets/policies/:id/rollover
  - Computes previous period remaining, creates rollover doc, adjusts budget
  - GET /ai-budgets/policies/:id/rollovers for history
- Enforcement check: POST /ai-budgets/check (pre-flight, no spend recorded)
  - Model allowlist + threshold evaluation, returns verdict + reasons
- New types: CostDashboardQuerySchema, BudgetRolloverSchema
- New repo functions: listAllSpendEntries, createRollover, listRollovers
- New Cosmos container: ai_budget_rollovers
- 1,316 tests passing (9 new)
2026-03-20 03:26:23 -07:00
saravanakumardb1
84dc348687 feat(platform): Phase 2 — Agent Runtime Orchestration
- New: agents/executor.ts — full agent execution engine
  - Multi-step pipeline: prompt_assembly → tool_execution → finalize
  - AbortController-based cancellation with in-memory tracking
  - Token usage aggregation across tool calls
  - Review-required tool gating (pauses run, returns review_required)
  - Step event streaming for SSE consumers
- New: agents/tool-registry.ts — global tool registry
  - Register/list/validate tools with risk levels + review flags
- New: agents/executor-routes.ts — 11 endpoints, 14 tests
  - POST /agents/execute, POST /runs/:id/cancel
  - GET /agents/active-runs, GET /runs/:id/children, GET /runs/:id/tree
  - GET /agents/:id/metrics, GET /runs/:id/stream (SSE)
  - GET /tools, POST /tools/validate, POST /agents/:id/schedule
- Enhanced: runs/repository.ts — added listChildRuns() for DAG query
- 1,307 tests passing (14 new)
2026-03-20 03:20:31 -07:00
saravanakumardb1
15e24e5710 feat(platform): Phase 1 — Durable Event Bus + Worker Runtime
- New module: event-subscriptions/ (types, repository, routes, 15 tests)
  - Subscription CRUD: create/list/get/update/delete event subscriptions
  - DLQ: list/retry/delete/purge dead-letter queue entries
  - Event replay: POST /events/replay by topic + time range
- New lib: event-dispatcher.ts — subscription-driven dispatch with retry + DLQ
- New lib: event-store-bridge.ts — persistent event log for replay capability
- Worker runtime hardening (jobs/runner.ts):
  - Concurrency limit (MAX_CONCURRENT_JOBS=5)
  - Stuck-job recovery (10min threshold)
  - Graceful shutdown (30s drain)
  - Active job tracking + diagnostics (getActiveJobs/getActiveJobCount)
  - Per-job dedup (skip if already running)
- Wired dispatcher + event-subscriptions into server.ts startup
- Cosmos containers: event_subscriptions, event_dlq, event_log
- 1,293 tests passing (15 new)
2026-03-20 03:12:54 -07:00
saravanakumardb1
9e510f7b49 test(scim): add 7 tests for stats, pause, resume, delete endpoints
- routes.test.ts: add mock functions for deleteConnector, getConnectorStats
- 7 new tests: stats endpoint, pause active, pause rejects non-active,
  resume paused, resume rejects non-paused, delete paused, delete rejects active
- Total: 11 SCIM tests (was 4)
2026-03-20 01:06:07 -07:00
saravanakumardb1
28b6668fb1 fix(knowledge): align searchChunks scoring with routes, add 5 new tests
- repository.ts: searchChunks now includes tag matching (+2 per tag hit)
  consistent with scoreChunk() in routes.ts
- routes.test.ts: add 5 new tests — stats endpoint, delete draft base,
  reject non-draft delete, delete source, search chunks
- Total: 9 knowledge tests (was 4)
2026-03-20 01:04:32 -07:00
saravanakumardb1
036d17d8f0 fix(agents): use NotFoundError for missing resources, add deprecate+published tests
- routes.ts: use NotFoundError (404) instead of BadRequestError (400)
  for missing agent by key and missing published version
- routes.test.ts: fix expectation for unknown key (400→404),
  add 4 new tests: deprecate success, deprecate already-deprecated guard,
  GET published success, GET published 404 when none
- Total: 13 agent tests (was 8)
2026-03-20 01:02:36 -07:00
saravanakumardb1
d073122a48 feat(scim): deepen SCIM provisioning — stats, delete, pause/resume
- repository.ts: add ScimConnectorStats interface, getConnectorStats (user/group/event counts),
  deleteConnector
- routes.ts: 4 new endpoints — GET /scim/connectors/:orgId/:id/stats,
  DELETE /scim/connectors/:orgId/:id (must be paused first),
  POST /scim/connectors/:orgId/:id/pause, POST /scim/connectors/:orgId/:id/resume
- Existing 4 tests unchanged, typecheck clean
2026-03-20 00:44:49 -07:00
saravanakumardb1
20663d7078 feat(knowledge): deepen Knowledge/RAG — search, stats, delete endpoints
- repository.ts: add searchChunks (term-based text search with scoring),
  getBaseStats (source/chunk/token counts), deleteSource, deleteBase
- routes.ts: 4 new endpoints — GET /knowledge/bases/:id/stats,
  DELETE /knowledge/bases/:id (draft only), DELETE /knowledge/bases/:id/sources/:sourceId,
  POST /knowledge/bases/:id/search (text search with previews)
- Existing 4 tests unchanged, typecheck clean
2026-03-20 00:42:12 -07:00
saravanakumardb1
ae87371b3a feat(agents): deepen agent registry — version lifecycle, lookup by key, delete
- repository.ts: add getAgentByKey, updateAgentVersion, getPublishedVersion, deleteAgent
- routes.ts: 5 new endpoints — GET /agents/by-key/:key, GET /agents/:id/published,
  POST /agents/:id/versions/:vId/publish (auto-deprecates previous),
  POST /agents/:id/versions/:vId/deprecate, DELETE /agents/:id (draft only)
- routes.test.ts: 6 new tests (8 total) — publish lifecycle, deprecate guard,
  key lookup, delete draft-only guard
- repository.test.ts: 1 existing test unchanged
2026-03-20 00:39:24 -07:00
saravanakumardb1
0195cde1c0 feat(orgs): deepen Org/Workspace RBAC — role hierarchy, permissions, delete endpoints
- types.ts: add ROLE_HIERARCHY (owner>admin>member>viewer), ROLE_PERMISSIONS matrix (11 permissions),
  hasPermission() and canManageRole() helpers
- repository.ts: add deleteMembership, getUserMembership, deleteOrganization, deleteWorkspace
- routes.ts: 4 new endpoints — DELETE /orgs/:id (owner only), DELETE /orgs/:id/workspaces/:wsId,
  DELETE /orgs/:id/memberships/:mbrId (RBAC enforced), GET /orgs/:id/permissions
- RBAC enforcement: role update checks actor outranks target, cannot remove owner, cannot
  assign role >= own level
- routes.test.ts: 6 new tests (8 total) — owner-only delete, member removal RBAC,
  permissions endpoint, non-member handling
- repository.test.ts: 1 existing test unchanged
2026-03-20 00:36:02 -07:00