Update upulse commands and UI server to await all async store methods. - Make CLI action callbacks async (workflow create, timeline, list, inspect events/object) - Make daemon status function async - Make all UI server handler functions async with awaited store calls - Fix Promise.all patterns for getObject calls in map functions - Fix scopedStore.close() calls to be awaited
Made-with: Cursor
Update all *.test.ts files to properly await the async PulseStore, ScopedStore, and defs functions. Fix gc.test.ts timing issues for async GC trigger, fix bad await assignment targets, and correct .length access on Promise objects.
Made-with: Cursor
- PulseStore/ScopedStore 接口方法返回 Promise<T>
- 所有 store 实现方法改为 async(bun:sqlite 同步调用外包 async)
- defs.ts, projection-engine.ts, gc.ts 公共函数异步化
- index.ts 中 store 调用加 await
- rules/health.ts rebuildHealth 函数异步化
- 核心异步化完成,支持 CF D1 等异步数据库运行时
Breaking Changes:
- All PulseStore methods now return Promise<T>
- Consumer code must add await for all store operations
- Tests need to be updated to use async/await patterns
- Extract core logic into testable performRollback(opts) function
- CLI action now delegates to performRollback and prints output
- Tests cover: dry-run, event export/delete, git checkout, missing
commit error, noop when already at target, dump metadata
- All tests use tmpdir, no dependency on ~/.upulse
- WorkflowCheckpoint caches lastEventId, topic summaries, and per-topic events
- First tick: full read (getAfter(0)), subsequent ticks: incremental (getAfter(lastEventId))
- Newly written role events also update checkpoint in-place
- No interface changes, no new files
- ENGINE_DIR = ~/.upulse/engine for meta coder/reviewer/tester/promoter
- REPO_DIR still used for coding workflow
- Tester accepts buildCmd/testCmd opts, no longer hardcoded to monorepo paths
- Init engine dir with package.json + tsconfig.json + git repo
Tester was failing with ENOENT because cwd pointed to
/home/azureuser/repos/packages/pulse (nonexistent) instead of
/home/azureuser/repos/pulse/packages/pulse.
- cooldownMs: 0 for both coding and meta workflow rules
- logTick wrapper prints timestamp + elapsed ms per tick
- start-daemon.sh loads secrets before starting bun
- pulse-workflow.service systemd unit (enabled + started)
- ArchitectMeta now includes targetFiles, changes (file→description), and verification criteria
- CoderMeta prepPrompt explicitly consumes architect.changes, architect.verification, and reviewer.rejectionReason on retry
- ReviewerMeta now outputs verdict, rejectionReason, and monotonic retryCount (starting from 0)
- Moderator enforces retryCount < 3 limit — forces closer when exceeded
- Updated mock implementations, role factories, and e2e to match new meta structures
- Added test for retry limit (retryCount >= 3 → closer)
- analyst: structured JSON output via tool_choice (score, highlights, issues, roleAnalysis with eventId refs)
- renderer: pure code HTML template — dark theme, gantt bar, role cards, verdict badges
- report-live.ts: e2e test script, reads coding workflow DB → generates HTML report
- renderer-llm.ts: kept as reference (LLM version, not used — timeout issues)
- 2 unit tests pass, live test: 17.9s end-to-end
- council-v2-live.ts: coder/reviewer now use createCoderRole/createReviewerRole
- Removed inline runCursorAgent (moved to agent-executor.ts)
- reviewer verdict via LLM₂ tool_choice instead of includes('rejected')
- Live verified: architect→coder→reviewer(approved)→closer in 135s
- createAgentExecutorRole: prepPrompt → agent.run → LLM₂ tool_choice → meta
- createCursorRunner: extracts Cursor CLI into AgentRunner interface
- Coder role: LLM₂ extracts filesChanged + testsPassed via tool_choice
- Reviewer role: LLM₂ extracts verdict via tool_choice (no more includes hack)
- defaultMeta fallback when LLM₂ fails or returns no tool_call
- 5 new agent-executor tests, 24 total pass
Simplified structure with inline code block for WorkflowType,
streamlined section headings, and tighter prose while retaining
all key topics: START/END automaton, pure roles, Moore-machine
diff-driven ticks, and source file references.
Made-with: Cursor
- Role<Meta> = (chain, topicId, store) => Promise<Meta>
- MetaOf<R> extracts Meta from Role type
- RoleOutput<Roles> = discriminated union { role: K, meta: MetaOf<Roles[K]> }
- Moderator receives RoleOutput, switch on role narrows meta type
- WorkflowType simplified: no projection field, just name + roles + moderator
- Adapter builds per-topic summary internally
- coding-workflow: ArchitectMeta, CoderMeta, ReviewerMeta, CloserMeta
- -538/+326 lines — simpler AND more type-safe