- Add `retention` field to SenseConfig (default 10000 max rows)
- Parse optional `retention` positive integer in nerve.yaml sense config
- Prune old _signals rows every 100 inserts for amortized performance
- Pass retention from config through sense-worker to openSenseDb
- Add unit tests for config parsing and runtime pruning
Every sense now gets a _signals table (id, payload, timestamp) created
automatically. When compute() returns non-null, the signal is persisted
to the sense's own SQLite DB before being sent to the Signal Bus.
This makes `nerve sense query <name>` return signal history out of the
box — no manual INSERT needed in compute functions.
CLI's pickDefaultPreviewTable now prioritizes _signals over other tables.
The /api/kill-workflow endpoint and all callers (dashboard, HttpTransport)
now consistently use 'runId' instead of 'threadId', matching the handler
name killWorkflowByRunId.
Fixes review feedback on PR #138.
- Default bind host to 127.0.0.1 (no auth in Phase 1)
- POST /api/trigger-workflow reads optional prompt/maxRounds/dryRun from body
- POST /api/kill-workflow: threadId required, name optional (log only)
Refs #133
When a workflow file changes while runs are active, defer the
drain+respawn until all active threads finish instead of immediately
killing them.
- Add drainWhenIdle() with pendingDrains tracking
- Wire maybeDeferredHotReloadDrain into thread-event and workflow-error paths
- Clean up pendingDrains on worker crash and stop()
- 6 new test cases in hot-reload.test.ts
Fixes#134
- Rename logs & workflow_runs table column ts → timestamp (breaking, no migration)
- Update all SQL, types, mocks, CLI output, and tests
- Integration tests use mkdtempSync to avoid stale DB conflicts
Fixes#113
- Rename logs table column ts → timestamp (no migration, breaking)
- Update all SQL, type definitions, and consumers
- Integration tests use mkdtempSync to avoid stale DB conflicts
Fixes#113
- Role<Meta> now takes (start: StartSignal, messages: WorkflowMessage[])
- messages no longer contains the __start__ frame
- Add ModeratorContext<M> discriminated union (kind: start | step)
- Moderator receives typed context instead of raw StartSignal | RoleSignal union
- workflow-worker separates start from role messages throughout
Refs #100
Move wire protocol types and parseDaemonIpcRequest into @uncaged/nerve-core so CLI and daemon share one definition. Type sendAndReceive message as DaemonIpcRequest. Align workflow trigger CLI with daemon (prompt, maxRounds from --payload JSON).
Made-with: Cursor
Update test expectations after workflow reflexes were removed from
YAML config and type signatures were tightened:
- core/config: workflow reflex tests now expect 'not supported' error
- cli/workflow: partitionWorkflowMessage test uses strict typed params
- daemon/crash-recovery: remove triggerPayload from resume-thread assertion
- daemon/daemon-ipc: trigger-workflow sends prompt+maxRounds
- daemon/kernel-workflow: use Sense-driven workflow trigger pattern
Fixes 12 test failures across core, cli, and daemon packages.
Refs #88, #89
- Add isPlainRecord() type guard to eliminate 'as Record<string, unknown>' casts
- Replace 'as any' with properly typed assertions in start.ts
- Remove 'null as unknown as' pattern in kernel.ts
- Add type predicates for array narrowing (item is string)
- Improve IPC message type narrowing in daemon-client.ts and ipc.ts
- Type better-sqlite3 and drizzle return values properly
No runtime behavior changes.
- Create packages/store/ with log-store, log-archive, blob-store (~900 LOC)
- daemon depends on @uncaged/nerve-store (workspace:*)
- CLI depends on @uncaged/nerve-store, delete daemon-types.ts
- Move store-related tests to packages/store/src/__tests__/
- All store tests pass (73/73), no new regressions
- Filter __start__ messages in getThreadRoundCount SQL to fix round offset
- Remove duplicate parseWorkflowField, use parseSenseWorkflowDirective
- Remove unnecessary double casts in workflow CLI
- Add runtime validation for Role meta in workflow-worker
- Export DEFAULT_ENGINE_MAX_ROUNDS from types.ts
小橘 🍊(NEKO Team)
- Replace loose payload types with WorkflowLaunchParams { prompt, maxRounds }
- Add SenseResult.workflow field with pipe-separated format (name|rounds|prompt)
- Add parseWorkflowField utility and routeSenseComputeOutput in @nerve/core
- Integrate sense→workflow routing in kernel
- Remove deprecated workflow reflex kind from ReflexScheduler
- Update all test files to use new type-safe interfaces
小橘 🍊(NEKO Team)
Implements the workflow thread CLI command that retrieves
workflow execution context (logs, events, state) for a given run.
- Add 'nerve workflow thread <runId>' subcommand
- Add log-store query API in daemon
- Add tests for CLI and log-store
- Export new daemon types for thread data
小橘 <xiaoju@shazhou.work>
The original code only accepted object-type triggerPayload, silently
discarding string values by replacing them with {}. This meant
`nerve workflow trigger <name> --payload '"some string"'` would
lose the payload entirely.
Changed to `triggerPayload ?? {}` so strings (and other non-null
values) pass through correctly.
小橘 🍊(NEKO Team)
Replace tsup (esbuild-based) with rslib (rspack-based) across all packages.
tsup's built-in nodeProtocolPlugin strips the 'node:' prefix from all
Node.js builtins. Unlike node:fs etc., node:sqlite has no unprefixed
form, causing ERR_MODULE_NOT_FOUND at runtime. rslib handles node:
imports correctly without any workarounds.
Changes:
- Replace tsup.config.ts with rslib.config.ts in core, daemon, cli
- Swap tsup → @rslib/core in devDependencies
- Fix log-store.ts params type (Record<string, unknown> → Record<string, string | number>)
- Fix logStream.fd type cast in start.ts
- Exclude __tests__ from CLI tsconfig to avoid DTS errors
- All 356 tests pass, nerve init works correctly
Closes#70
小橘 🍊(NEKO Team)
tsup's built-in node-protocol-plugin strips the 'node:' prefix from
all builtins. Unlike node:fs etc., node:sqlite has no unprefixed form,
causing ERR_MODULE_NOT_FOUND at runtime.
- Add onSuccess hook to both cli and daemon tsup configs to restore
'node:sqlite' imports in bundled output
- Fix log-store params type to Record<string, string | number>
小橘 🍊(NEKO Team)
- Upgrade drizzle-orm from 0.43.1 to 1.0.0-beta.23
- Replace better-sqlite3 with node:sqlite (DatabaseSync) in:
- sense-runtime.ts (Drizzle driver)
- log-store.ts (raw SQL)
- all test files
- Replace sqlite.pragma() with sqlite.exec('PRAGMA ...')
- Replace sqlite.transaction() with manual BEGIN/COMMIT/ROLLBACK
- Update CLI init command to verify node:sqlite instead of better-sqlite3
- Remove better-sqlite3 and @types/better-sqlite3 from dependencies
- Zero native addons remaining in the monorepo 🎉Closes#67
小橘 <xiaoju@shazhou.work>
- Add engines >= 22.5.0 to root and cli package.json (node:sqlite requirement)
- Remove unused @types/better-sqlite3 from cli devDeps (leftover from sql.js migration)
- Add files/publishConfig to core package.json (parity with other packages)
- Fix daemon test type errors: add getAllWorkflowRuns to mock LogStore,
fix array destructuring on mock.calls, fix sense-runtime callback signatures
All 356 tests pass across all packages.
小橘 🍊(NEKO Team)
- Add .cursor/rules/no-dynamic-import.mdc: ban dynamic import() in
production code with documented exceptions
- Add .cursor/rules/gitea-access.mdc: tea CLI usage guide
- Add explanatory comments on the 2 legitimate dynamic imports in
sense-runtime.ts and workflow-worker.ts
Ignore SIGINT/SIGTERM only when fork IPC is active (process.send) so terminal signals do not race the kernel shutdown in nerve dev, without breaking standalone worker CLIs (fixes#55).
Pipe worker stderr through the parent with a rolling capture buffer; log exit signal name and stderr tail on worker exit (fixes#56). Apply the same exit logging to workflow workers.
Made-with: Cursor