feat(reconciliation): implement deterministic state reconciliation engine and post-commit hook
- Implement ReconciliationEngine in server/src/handlers/reconciliation.rs - Auto-transition ADRs to implemented, resolve tech debts, and cascade task unblocking - Ingest git commit events via POST /api/git/commit and scripts/git-reconcile.py post-commit hook - Add universal pagination, search filtering, and keyboard navigation to dashboard - Implement non-destructive task TTL expiry sweeper and gate verification - Implements: ADR-0102, ADR-0103
This commit is contained in:
1 parent
ec977c24dd
commit
8f924b793a
16 files changed
+2622
-163
No files matched your search
+28
-1
@@ -102,10 +102,37 @@ pub async fn ttl_sweeper_worker(state: Arc<MemoryState>) {
|
||||
.unwrap_or_default()
|
||||
.as_secs();
|
||||
|
||||
let mut expired_tasks = Vec::new();
|
||||
state.project.tasks.modify(|tasks| {
|
||||
tasks.retain(|t| t.expires_at.is_none_or(|exp| exp > now));
|
||||
for t in tasks.iter_mut() {
|
||||
if let Some(exp) = t.expires_at {
|
||||
if exp <= now && t.is_active() {
|
||||
t.status = "expired".to_string();
|
||||
t.updated_at = now;
|
||||
expired_tasks.push(t.id.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
for tid in expired_tasks {
|
||||
state.record_activity(
|
||||
"task_expired",
|
||||
&format!("Task {} expired due to TTL", tid),
|
||||
Some("expired"),
|
||||
);
|
||||
state.broadcast_task_event(crate::models::TaskEvent {
|
||||
task_id: tid,
|
||||
status: "expired".to_string(),
|
||||
action: Some("ttl_expire".to_string()),
|
||||
result: Some(serde_json::json!({ "status": "expired" })),
|
||||
error: None,
|
||||
timestamp: now,
|
||||
session_id: None,
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
|
||||
state.telemetry.handoff_memos.modify(|memos| {
|
||||
memos.retain(|m| m.expires_at.is_none_or(|exp| exp > now));
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user