Skip to content

feat(plan): Track synchronization state for plan executions - #816

Merged
haiphucnguyen merged 3 commits into
mainfrom
feature/improvements
Nov 13, 2026
Merged

haiphucnguyen merged 3 commits into
mainfrom
feature/improvements

Conversation

@haiphucnguyen

Copy link
Copy Markdown
Collaborator

⚠️ First-time contributor? This PR cannot be merged until you sign the CLA.
The CLA Assistant bot will post a comment below — reply to it with exactly:
I have read the CLA Document and I hereby sign the CLA
(Separate from this: all commits must also be signed off with git commit -s — see the Checklist.)

Summary

  • Adds synced_at column to plan_executions to track data synchronization state.
  • Introduces PlanExecutionCodec to manage data mapping for synchronization transfers.
  • Updates database access logic to use the new synced_at timestamp for data integrity checks.

Related Issue(s)

Type of Change

  • 🐛 Bug fix
  • ✨ New feature
  • 💥 Breaking change
  • 📝 Documentation
  • ♻️ Refactor (no functional change)
  • 🧪 Tests
  • 🔧 Chore / tooling / CI

What Changed & Why

How to Test

./gradlew test

Screenshots / Recordings (if applicable)

Checklist

  • I have read the CONTRIBUTING guide
  • I signed the CLA (first-time contributors — reply to the CLA Assistant bot comment)
  • My branch is up to date with main
  • I ran ./gradlew spotlessApply and ./gradlew detekt locally
  • I ran ./gradlew test and all tests pass
  • I added/updated tests for my changes (if applicable)
  • I added/updated documentation (if applicable)
  • My commits are signed off (DCO) — git commit -s
  • This PR is focused on a single feature/fix

Additional Notes

- Adds `synced_at` column to plan_executions to track data synchronization state.
- Introduces `PlanExecutionCodec` to manage data mapping for synchronization transfers.
- Updates database access logic to use the new `synced_at` timestamp for data integrity checks.

BREAKING CHANGE: The plan execution data model now includes a `synced_at` timestamp, requiring schema migration and updates to data handling logic in `DatabaseManager`.
Copilot AI lite review requested due to automatic review settings November 13, 2026 07:06

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved critical synchronization race and deletion-handling issues, plus a non-reversible codec and missing coverage for new sync paths, could cause data loss or stale remote state.

5 open issues
What changed in this PR

Adds synchronization tracking and server merge support for plan execution records.

Changes:

  • Adds nullable synced_at storage, migration handling, and SQLDelight type adaptation.
  • Introduces shared encoding and decoding utilities for plan execution data.
  • Adds synchronization events, unsynced-record discovery, sync marking, and server upsert handling.
File Description
shared-jvm/​src/​main/​sqldelight/​migrations/​69.sqm Registers the database migration for plan execution synchronization state.
shared-jvm/​src/​main/​sqldelight/​io/​askimo/​core/​db/​sqldelight/​PlanExecutions.sq Adds the nullable synced_at column and synchronization-related SQL queries.
shared-jvm/​src/​main/​kotlin/​io/​askimo/​core/​plan/​repository/​PlanExecutionRepository.kt Implements synchronization state management, push events, unsynced lookup, and server upserts.
shared-jvm/​src/​main/​kotlin/​io/​askimo/​core/​plan/​domain/​PlanExecutionCodec.kt Centralizes serialization and deserialization of plan execution inputs and step outputs.
shared-jvm/​src/​main/​kotlin/​io/​askimo/​core/​db/​SqlDelightSchemaMigrations.kt Adds guarded migration handling for the synced_at column.
shared-jvm/​src/​main/​kotlin/​io/​askimo/​core/​db/​DatabaseManager.kt Configures the nullable Instant adapter for the synchronization timestamp.

Review effort: Lite

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Approval is blocked by a critical compatibility issue that makes existing plan executions unreadable and a moderate deletion-flow issue that can leave remote executions undeleted.

1 open issue
1 previously missed issue

In code that hasn't changed since last review

Medium severity Preserve a remote-delete tombstone before deleting executions

shared-jvm/​src/​main/​kotlin/​io/​askimo/​core/​plan/​repository/​PlanExecutionRepository.kt:146

The new caller contract is not satisfied by the current call graph: PlanService.deleteExecution (used by PlansViewModel) calls repository.delete directly, and there is no explicit remote-delete call before it. This hard-delete removes the only local evidence of the execution, so a remote copy cannot be removed once execution sync is enabled. Add a tombstone/remote-delete flow before deleting, or make the synchronization scope and this method's contract explicitly local-only rather than documenting a pairing that does not exist.

5 resolved since last review

Review effort: Lite

Comment on lines +29 to +32
fun decodeInputs(raw: String): Map<String, String> {
if (raw.isBlank() || raw == "{}") return emptyMap()
return json.decodeFromString(raw)
}
@haiphucnguyen
haiphucnguyen merged commit 497da27 into main Nov 13, 2026
13 of 14 checks passed
@haiphucnguyen
haiphucnguyen deleted the feature/improvements branch November 13, 2026 08:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants