PR #539 (6/10 rebased): feat: add opt-in LCM task suggestion tools#27
PR #539 (6/10 rebased): feat: add opt-in LCM task suggestion tools#27100yenadmin wants to merge 5 commits into
Conversation
…suggestion tools Rebased upstream PR Martian-Engineering#539 (Martian-Engineering#539) onto main with the 8 hotfix PRs (Martian-Engineering#572-Martian-Engineering#579) + Martian-Engineering#516 already in place. Inverse-merge resolution per refined policy: - engine.ts: 3-way UNION; preserved hotfixes (normalizeSummaryOverlapText, messageContentCoveredBySummary, clock.now(), TableColumnInfo cast) AND added pr-539's ObservedWorkStore + TaskBridgeSuggestionStore fields, inits, and getters. - migration.ts: kept main's Martian-Engineering#569+Martian-Engineering#574 migrations; injected pr-539's new ensureObservedWorkTables, ensureObservedWorkIndexes, ensureTaskBridgeSuggestionTables, ensureTaskBridgeSuggestionIndexes steps after ensureRollupViews. Fixed SummaryColumnInfo->TableColumnInfo in addColumnIfMissing helper. - plugin/index.ts: kept main's tool wiring; added imports + registerTool calls for createLcmWorkDensityTool plus gated createLcmTaskSuggestionsTool / createLcmTaskSuggestionReviewTool. - openclaw.plugin.json: union; appended lcm_task_suggestion_review, lcm_task_suggestions, lcm_work_density to contracts.tools and added schema/uiHints for taskBridgeToolsEnabled while preserving rollup token-budget keys. - db/config.ts: union; both rollup token-budget knobs and taskBridgeToolsEnabled config field + env wiring. - timezone-windows.ts: took pr-539's startOfWeekDayString export. - README.md / docs/configuration.md: added LCM_TASK_BRIDGE_TOOLS_ENABLED and taskBridgeToolsEnabled docs alongside main hotfix doc lines. - test/engine.test.ts, test/rollup-store-builder.test.ts, src/tools/lcm-recent-tool.ts, src/rollup-builder.ts, src/store/rollup-store.ts: took main (hotfix code only). - New pr-539 files (observed-work-store, task-bridge-suggestion-store, lcm-task-suggestions-tool, lcm-work-density-tool, plus tests/specs/ changesets) taken cleanly. Validation: 0 conflict markers, npm run build clean, 988/988 tests pass.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
Caution Review failedPull request was closed or merged during review 📝 WalkthroughWalkthroughThis PR introduces observed-work density tracking, event observations, and a task-bridge suggestion ledger for LCM. New database stores persist extracted work items and events from conversation summaries, enable incremental processing with cursor-based replay guards, and expose read-only density queries and suggestion management via opt-in tools. ChangesObserved Work, Event Observations, and Task Bridge Suggestions
Sequence Diagram(s)Skipped (configuration-heavy changes with independent store operations; no multi-component sequential flows requiring visualization). Estimated code review effort🎯 5 (Critical) | ⏱️ ~90 minutes Rationale: Substantial changes spanning five store implementations with complex SQL (conflict handling, cursor semantics, budget-aware query trimming), regex-driven evidence extraction with replay guards, three tools with parameter validation and normalization, transactional concurrency semantics, and 1900+ lines of heterogeneous tests validating edge cases (rowid drift, same-second summaries, source deduplication, review transitions). Requires careful review of: (1) cursor idempotency & missing-summary-ID fallback logic, (2) conflict-resolution merge semantics (terminal status, monotonic counters, confidence clamping), (3) transactional boundaries in bulk operations, (4) regex classification correctness and negation handling, (5) timestamp canonicalization and timezone-aware period arithmetic, (6) output budget trimming and accounting accuracy. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Review rate limit: 0/5 reviews remaining, refill in 57 minutes and 13 seconds. Comment |
There was a problem hiding this comment.
Pull request overview
Adds an opt-in “observed work” read model and associated tools for summarizing work density, plus an inert task-suggestion ledger (preview/record + review) that explicitly does not mutate external tasks.
Changes:
- Introduces SQLite tables + stores for observed work items/sources/state and task-bridge suggestions.
- Adds
lcm_work_densitytool and opt-inlcm_task_suggestions/lcm_task_suggestion_reviewtools (gated bytaskBridgeToolsEnabled). - Updates plugin wiring, config/env, manifest, docs, and adds comprehensive tests/specs/changesets.
Reviewed changes
Copilot reviewed 19 out of 19 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
src/db/migration.ts |
Adds observed-work + task-bridge suggestion tables and indexes; small type alias cleanup. |
src/store/observed-work-store.ts |
Implements observed work persistence + density querying with optional source loading and limits. |
src/tools/lcm-work-density-tool.ts |
Exposes observed work density as a tool with period parsing and output-budget trimming. |
src/store/task-bridge-suggestion-store.ts |
Implements inert suggestion ledger (upsert pending, list, review). |
src/tools/lcm-task-suggestions-tool.ts |
Generates/records suggestions from observed work and provides a review tool. |
src/timezone-windows.ts |
Exports startOfWeekDayString for Monday-start week windows on YYYY-MM-DD. |
src/plugin/index.ts |
Registers lcm_work_density and conditionally registers task suggestion tools when enabled. |
src/engine.ts |
Wires new stores into LcmContextEngine and exposes getters. |
src/db/config.ts |
Adds taskBridgeToolsEnabled with LCM_TASK_BRIDGE_TOOLS_ENABLED wiring. |
openclaw.plugin.json |
Adds tool contracts + config schema/uiHints for taskBridgeToolsEnabled. |
test/observed-work-store.test.ts |
Tests migrations, density semantics, period handling, source redaction, and output budget trimming. |
test/task-bridge-suggestion-store.test.ts |
Tests suggestion ledger behavior and tool flows without any external task writes. |
docs/configuration.md / README.md |
Documents the new opt-in config/env var. |
specs/lcm-observed-work-density-option-b.md |
Design/spec doc for observed work density (Option B). |
specs/lcm-task-bridge-option-c-experimental.md |
Design/spec doc for experimental suggestion-ledger bridge (Option C). |
.changeset/*.md |
Release notes for observed work density and suggestion tooling/storage. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…erministic outcome)
…GIN IMMEDIATE bypass); add bulk tests Wave 2 fix on PR #27 / rebase/539. Wave 1 (1df72b9) introduced a private runInTransaction helper that called raw BEGIN IMMEDIATE / COMMIT / ROLLBACK on the shared DatabaseSync handle, with a fallback nested-transaction path guarded by `(this.db as unknown as { inTransaction?: boolean }).inTransaction`. Two problems with that: 1. CRITICAL-1 — `node:sqlite`'s DatabaseSync does NOT expose `inTransaction` (that's a better-sqlite3 API). The fallback path was unreachable code. 2. CRITICAL-2 — the helper bypassed `withDatabaseTransaction` from src/transaction-mutex.ts, the per-database async mutex that serializes concurrent transaction entry points sharing the same DB handle. That's the exact race the mutex was built to fix (lossless-claw#260): two async paths racing BEGIN on a shared connection blow up with "cannot start a transaction within a transaction". Fix: replace `runInTransaction` with `withDatabaseTransaction(db, "BEGIN IMMEDIATE", ...)`. That's async, so `bulkUpsertSuggestions` and `upsertSuggestion` become async. The tool callsite (lcm-task-suggestions-tool record path) was already in an async execute() — now awaits the bulk call. Per-row failure semantics (MAJOR-1 in audit): pre-Wave-1, a bad row didn't poison the batch. Post-Wave-1, one FK-deletion race in 50 rows aborted the whole transaction. Restored with per-row SAVEPOINTs inside the outer transaction — a row that throws during INSERT (e.g. concurrent FK-delete of its work item or source evidence) is demoted to a new "skipped" outcome. The result array stays order-preserving so callers can correlate inputs ↔ results positionally. Input validation errors (bad confidence, blank ID, non-pending status, missing taskId for targeted kinds, no source IDs) still throw before the transaction opens — caller gets the same fast-fail. Empty-input early return preserved (no transaction opened for `[]`). Tests (MAJOR-2): added bulkUpsertSuggestions describe block with 4 cases — empty input, mixed insert+refresh, preserved_reviewed determinism with order preservation, mid-batch skipped row leaving good rows committed. Existing upsertSuggestion tests migrated to async/await; validation-error tests use `rejects.toThrow` since async functions convert sync throws to rejections. Total: 992 tests pass (988 baseline + 4 new). Build clean.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 19 out of 19 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…ions on top PR #27 (rebase/539) carried older versions of observed-work-store, work-density-tool, and migration.ts that pre-dated PR #20/#21/#22/#25/#28 hardening on release/v0.9.4. This commit takes the release/v0.9.4 versions of those files as the base and layers PR #27's NEW work on top: - KEPT (PR #27 additions, layered on release): - bulkUpsertSuggestions API (uses release's mutex routing + per-row SAVEPOINT) - getSuggestionConversationId helper - taskBridgeToolsEnabled config flag - reviewSuggestion suggestionId trim - lcm_task_suggestions + lcm_task_suggestion_review tools (gated) - TaskBridgeSuggestionStore engine wiring + getter - PORT-FORWARDED from release/v0.9.4: - src/store/observed-work-store.ts (cursor state, getItem, listItems, etc.) - src/store/event-observation-store.ts (NEW from release; wired in engine) - src/observed-work-extractor.ts (NEW from release; NEGATED_COMPLETION_RE, fingerprintVersion, clearProcessingCursor) - src/tools/lcm-work-density-tool.ts (release hardening) - src/tools/lcm-event-search-tool.ts (NEW from release) - src/db/migration.ts (release index set) - src/db/config.ts (observedWorkMaintenanceEnabled flag preserved) - src/plugin/index.ts (release gating + PR #27 task-suggestions blocks) - src/engine.ts (release ObservedWorkExtractor + EventObservationStore wiring, pendingRebuild + clearProcessingCursor on extraction failure) - test/observed-work-store.test.ts (release version aligned with new store API) - MERGED (release base + PR #27 additions): - src/store/task-bridge-suggestion-store.ts: MAX_SUGGESTION_SOURCE_IDS=50 cap, chunked source-id IN(...) lookup, ORDER BY suggestion_id ASC tiebreaker, SQLInputValue typing — all from release; bulkUpsertSuggestions, getSuggestionConversationId, "skipped" outcome, savepoint counter — from PR #27. - src/db/config.ts: both observedWorkMaintenanceEnabled (from release) and taskBridgeToolsEnabled (from PR #27). - src/plugin/index.ts: gates work-density + event-search behind observedWorkMaintenanceEnabled; gates task-suggestions tools behind taskBridgeToolsEnabled. - ADDED to openclaw.plugin.json: - lcm_event_search to contracts.tools (was missing — manifest drift guard caught it) - observedWorkMaintenanceEnabled in uiHints + configSchema Tests: 1006/1006 pass (was 992 before; release hardening added more coverage). Net new tsc errors: 0 (332 vs 342 baseline = 10 fewer).
Conflict resolution: took theirs (rebase/539 port-forwarded release + layered PR #27 on top). New tools: lcm_task_suggestions + lcm_task_suggestion_review (gated behind taskBridgeToolsEnabled flag, default off). New store API: bulkUpsertSuggestions (per-row SAVEPOINT, skipped outcome), getSuggestionConversationId (cross-conversation review prevention). Verified all PR #20-#28 hardening preserved.
|
Merged into |
Rebased upstream Martian-Engineering/lossless-claw#539 onto our test fork's
main, which already carries the 8 hotfix PRs (Martian-Engineering#572-Martian-Engineering#579) plus PR Martian-Engineering#516.Resolution strategy: inverse merge
pr-539was branched from an older main that predates the hotfix stack, so a literal "take pr-539" would delete hotfix code. Started from main and layered pr-539's net-new code on top.Per-file resolution
src/engine.tsnormalizeSummaryOverlapText,messageContentCoveredBySummary,deps.clock.now(),TableColumnInfocast). Added pr-539'sObservedWorkStore+TaskBridgeSuggestionStorefields, inits, and getters.src/db/migration.tsensureObservedWorkTables,ensureObservedWorkIndexes,ensureTaskBridgeSuggestionTables,ensureTaskBridgeSuggestionIndexesmigration steps afterensureRollupViews. Also fixedSummaryColumnInfo->TableColumnInfoinaddColumnIfMissing(pr-539 already had the right type).src/plugin/index.tsregisterToolcalls forcreateLcmWorkDensityToolplus thetaskBridgeToolsEnabled-gatedcreateLcmTaskSuggestionsTool/createLcmTaskSuggestionReviewTool.openclaw.plugin.jsonlcm_task_suggestion_review,lcm_task_suggestions,lcm_work_densitytocontracts.tools. Added schema + uiHints fortaskBridgeToolsEnabledalongside main's rollup token-budget keys.src/db/config.tstaskBridgeToolsEnabledconfig field withLCM_TASK_BRIDGE_TOOLS_ENABLEDenv wiring.src/timezone-windows.tsstartOfWeekDayStringexport.README.md,docs/configuration.mdLCM_TASK_BRIDGE_TOOLS_ENABLED/taskBridgeToolsEnableddocumentation.test/engine.test.ts,test/rollup-store-builder.test.ts,src/tools/lcm-recent-tool.ts,src/rollup-builder.ts,src/store/rollup-store.tsobserved-work-store.ts,task-bridge-suggestion-store.ts,lcm-task-suggestions-tool.ts,lcm-work-density-tool.ts, plus tests, specs, changesets.Validation
npm run buildclean (815.6kb bundle)npm test: 988/988 passing (53/53 suites)Net diff
19 files changed, 3161 insertions(+), 9 deletions(-)
Summary by CodeRabbit
New Features
taskBridgeToolsEnabledandobservedWorkMaintenanceEnabledconfiguration options.Documentation
Tests