@autopilot-harness/cli 0.2.6 → 0.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/vendor/runtime.mjs +253 -46
- package/dist/init/types.d.ts +1 -1
- package/dist/init/types.js +1 -1
- package/package.json +5 -5
|
@@ -1159,9 +1159,10 @@ var StateStore = class _StateStore {
|
|
|
1159
1159
|
).run(nowIso(), conversationId);
|
|
1160
1160
|
}
|
|
1161
1161
|
/**
|
|
1162
|
-
* Column-only redeliver hold (recover claim sleep).
|
|
1163
|
-
*
|
|
1164
|
-
*
|
|
1162
|
+
* Column-only redeliver hold (recover claim sleep). Does not touch
|
|
1163
|
+
* chain_pending — callers that need disarm (executing / ambient non-resumeFix)
|
|
1164
|
+
* clearChainPending before this. Mid-fix ambient resumeFix keeps
|
|
1165
|
+
* chain_pending for abort wasArmed handoff.
|
|
1165
1166
|
*/
|
|
1166
1167
|
setPendingRedeliverHold(conversationId, at) {
|
|
1167
1168
|
if (this.isInvalidConversationId(conversationId)) {
|
|
@@ -1173,7 +1174,7 @@ var StateStore = class _StateStore {
|
|
|
1173
1174
|
}
|
|
1174
1175
|
this.db.prepare(
|
|
1175
1176
|
`UPDATE review_chains SET
|
|
1176
|
-
pending_redeliver_at = ?,
|
|
1177
|
+
pending_redeliver_at = ?, updated_at = ?
|
|
1177
1178
|
WHERE conversation_id = ?`
|
|
1178
1179
|
).run(stamp, nowIso(), conversationId);
|
|
1179
1180
|
}
|
|
@@ -2473,11 +2474,16 @@ var ReviewEngine = class {
|
|
|
2473
2474
|
const transcriptPath = input.transcriptPath?.trim() || void 0;
|
|
2474
2475
|
const events = transcriptPath ? readTranscriptTail(transcriptPath) : [];
|
|
2475
2476
|
if (chain.code_edited === 1) {
|
|
2476
|
-
|
|
2477
|
+
const tip = chain.pending_followup?.trim() ?? "";
|
|
2478
|
+
if (!isRecoverOrStuckFollowupMessage(tip)) {
|
|
2479
|
+
const fix = this.e2Fix(session, chain);
|
|
2480
|
+
if (fix) return fix;
|
|
2481
|
+
}
|
|
2477
2482
|
}
|
|
2483
|
+
const chainLive = this.store.getReviewChain(session.conversation_id) ?? chain;
|
|
2478
2484
|
const redelivered = this.tryRedeliverPending(
|
|
2479
2485
|
session.conversation_id,
|
|
2480
|
-
|
|
2486
|
+
chainLive,
|
|
2481
2487
|
events,
|
|
2482
2488
|
transcriptPath
|
|
2483
2489
|
);
|
|
@@ -2487,26 +2493,54 @@ var ReviewEngine = class {
|
|
|
2487
2493
|
}
|
|
2488
2494
|
if (this.pendingBlocksAdvance(
|
|
2489
2495
|
session.conversation_id,
|
|
2490
|
-
|
|
2496
|
+
chainLive,
|
|
2491
2497
|
events,
|
|
2492
2498
|
transcriptPath
|
|
2493
2499
|
)) {
|
|
2494
2500
|
return null;
|
|
2495
2501
|
}
|
|
2496
|
-
|
|
2497
|
-
|
|
2502
|
+
const chainAfterPending = this.store.getReviewChain(session.conversation_id) ?? chainLive;
|
|
2503
|
+
{
|
|
2504
|
+
const liveTip = chainAfterPending.pending_followup?.trim() ?? "";
|
|
2505
|
+
if (isRecoverOrStuckFollowupMessage(liveTip)) {
|
|
2506
|
+
return null;
|
|
2507
|
+
}
|
|
2508
|
+
}
|
|
2509
|
+
if (chainAfterPending.code_edited === 1) {
|
|
2510
|
+
const tip = chainAfterPending.pending_followup?.trim() ?? "";
|
|
2511
|
+
if (!isRecoverOrStuckFollowupMessage(tip)) {
|
|
2512
|
+
const fix = this.e2Fix(session, chainAfterPending);
|
|
2513
|
+
if (fix) return fix;
|
|
2514
|
+
const afterE2 = this.store.getReviewChain(session.conversation_id) ?? chainAfterPending;
|
|
2515
|
+
const afterTip = afterE2.pending_followup?.trim() ?? "";
|
|
2516
|
+
if (isRecoverOrStuckFollowupMessage(afterTip)) {
|
|
2517
|
+
const again = this.tryRedeliverPending(
|
|
2518
|
+
session.conversation_id,
|
|
2519
|
+
afterE2,
|
|
2520
|
+
events,
|
|
2521
|
+
transcriptPath
|
|
2522
|
+
);
|
|
2523
|
+
if (again) return again;
|
|
2524
|
+
return null;
|
|
2525
|
+
}
|
|
2526
|
+
}
|
|
2498
2527
|
}
|
|
2499
|
-
if (
|
|
2500
|
-
return this.
|
|
2528
|
+
if (chainAfterPending.confirm_left !== null && chainAfterPending.confirm_left > 0) {
|
|
2529
|
+
return this.e4Confirm(session, chainAfterPending);
|
|
2501
2530
|
}
|
|
2502
|
-
if (
|
|
2531
|
+
if (chainAfterPending.confirm_left === 0 || chainAfterPending.item_confirm_complete === 1 && chainAfterPending.confirm_left === null) {
|
|
2532
|
+
return this.e5Gate(session, chainAfterPending);
|
|
2533
|
+
}
|
|
2534
|
+
if (chainAfterPending.chain_pending === 0 && chainAfterPending.fix_round > 0 && chainAfterPending.code_edited === 0 && chainAfterPending.item_confirm_complete === 0 && isChecklistExecuting(session)) {
|
|
2503
2535
|
const cid2 = session.conversation_id;
|
|
2504
2536
|
const rearmed = this.store.exclusiveWrite(() => {
|
|
2505
2537
|
if (!this.sessionRunnable(cid2)) {
|
|
2506
2538
|
return { commit: false, value: false };
|
|
2507
2539
|
}
|
|
2508
2540
|
const fresh = this.store.getReviewChain(cid2);
|
|
2509
|
-
if (!fresh || fresh.code_edited === 1 || fresh.confirm_left !== null || fresh.item_confirm_complete === 1 || fresh.chain_pending === 1 || fresh.fix_round <= 0
|
|
2541
|
+
if (!fresh || fresh.code_edited === 1 || fresh.confirm_left !== null || fresh.item_confirm_complete === 1 || fresh.chain_pending === 1 || fresh.fix_round <= 0 || isRecoverOrStuckFollowupMessage(
|
|
2542
|
+
fresh.pending_followup?.trim() ?? ""
|
|
2543
|
+
)) {
|
|
2510
2544
|
return { commit: false, value: false };
|
|
2511
2545
|
}
|
|
2512
2546
|
this.store.updateReviewChain(cid2, { code_edited: 1 });
|
|
@@ -2517,12 +2551,48 @@ var ReviewEngine = class {
|
|
|
2517
2551
|
if (live?.code_edited === 1) {
|
|
2518
2552
|
const fix = this.e2Fix(session, live);
|
|
2519
2553
|
if (fix) return fix;
|
|
2554
|
+
const afterE2 = this.store.getReviewChain(cid2) ?? live;
|
|
2555
|
+
const afterTip = afterE2.pending_followup?.trim() ?? "";
|
|
2556
|
+
if (isRecoverOrStuckFollowupMessage(afterTip)) {
|
|
2557
|
+
const again = this.tryRedeliverPending(
|
|
2558
|
+
cid2,
|
|
2559
|
+
afterE2,
|
|
2560
|
+
events,
|
|
2561
|
+
transcriptPath
|
|
2562
|
+
);
|
|
2563
|
+
if (again) return again;
|
|
2564
|
+
return null;
|
|
2565
|
+
}
|
|
2520
2566
|
}
|
|
2521
2567
|
}
|
|
2522
2568
|
}
|
|
2523
2569
|
const chainNow = this.store.getReviewChain(input.conversationId) ?? chain;
|
|
2524
2570
|
if (chainNow.code_edited === 1) {
|
|
2525
|
-
|
|
2571
|
+
const tip = chainNow.pending_followup?.trim() ?? "";
|
|
2572
|
+
if (isRecoverOrStuckFollowupMessage(tip)) {
|
|
2573
|
+
const again = this.tryRedeliverPending(
|
|
2574
|
+
session.conversation_id,
|
|
2575
|
+
chainNow,
|
|
2576
|
+
events,
|
|
2577
|
+
transcriptPath
|
|
2578
|
+
);
|
|
2579
|
+
if (again) return again;
|
|
2580
|
+
return null;
|
|
2581
|
+
}
|
|
2582
|
+
const fix = this.e2Fix(session, chainNow);
|
|
2583
|
+
if (fix) return fix;
|
|
2584
|
+
const afterE2 = this.store.getReviewChain(session.conversation_id) ?? chainNow;
|
|
2585
|
+
const afterTip = afterE2.pending_followup?.trim() ?? "";
|
|
2586
|
+
if (isRecoverOrStuckFollowupMessage(afterTip)) {
|
|
2587
|
+
const again = this.tryRedeliverPending(
|
|
2588
|
+
session.conversation_id,
|
|
2589
|
+
afterE2,
|
|
2590
|
+
events,
|
|
2591
|
+
transcriptPath
|
|
2592
|
+
);
|
|
2593
|
+
if (again) return again;
|
|
2594
|
+
return null;
|
|
2595
|
+
}
|
|
2526
2596
|
}
|
|
2527
2597
|
const inChain = chainNow.chain_pending === 1 || chainNow.fix_round > 0 && isChecklistExecuting(session);
|
|
2528
2598
|
if (chainNow.confirm_left === null && chainNow.item_confirm_complete === 0 && inChain) {
|
|
@@ -2541,18 +2611,16 @@ var ReviewEngine = class {
|
|
|
2541
2611
|
const pending = chain.pending_followup?.trim();
|
|
2542
2612
|
if (!pending) return false;
|
|
2543
2613
|
if (events.length > 0 && automationFollowupPresent(events, pending)) {
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2614
|
+
const cleared = this.clearMatchingPendingAndArmAmbient(
|
|
2615
|
+
conversationId,
|
|
2616
|
+
pending
|
|
2617
|
+
);
|
|
2618
|
+
if (!cleared) {
|
|
2619
|
+
try {
|
|
2550
2620
|
const live = this.store.getReviewChain(conversationId)?.pending_followup?.trim() ?? "";
|
|
2551
|
-
if (live
|
|
2552
|
-
|
|
2553
|
-
}
|
|
2621
|
+
if (live) return true;
|
|
2622
|
+
} catch {
|
|
2554
2623
|
}
|
|
2555
|
-
} catch {
|
|
2556
2624
|
}
|
|
2557
2625
|
return false;
|
|
2558
2626
|
}
|
|
@@ -2560,17 +2628,23 @@ var ReviewEngine = class {
|
|
|
2560
2628
|
return true;
|
|
2561
2629
|
}
|
|
2562
2630
|
tryRedeliverPending(conversationId, chain, events, transcriptPath) {
|
|
2563
|
-
|
|
2631
|
+
let pending = chain.pending_followup?.trim() ?? "";
|
|
2632
|
+
if (!pending) {
|
|
2633
|
+
try {
|
|
2634
|
+
pending = this.store.getReviewChain(conversationId)?.pending_followup?.trim() ?? "";
|
|
2635
|
+
} catch {
|
|
2636
|
+
pending = "";
|
|
2637
|
+
}
|
|
2638
|
+
}
|
|
2564
2639
|
if (!pending) return null;
|
|
2565
2640
|
if (!transcriptPath) return null;
|
|
2566
2641
|
if (events.length > 0 && automationFollowupPresent(events, pending)) {
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
} catch {
|
|
2642
|
+
const cleared = this.clearMatchingPendingAndArmAmbient(
|
|
2643
|
+
conversationId,
|
|
2644
|
+
pending
|
|
2645
|
+
);
|
|
2646
|
+
if (cleared) {
|
|
2647
|
+
return null;
|
|
2574
2648
|
}
|
|
2575
2649
|
}
|
|
2576
2650
|
if (events.length > 0 && followupInFlight(events)) {
|
|
@@ -2590,10 +2664,16 @@ var ReviewEngine = class {
|
|
|
2590
2664
|
return { commit: false, value: null };
|
|
2591
2665
|
}
|
|
2592
2666
|
if (events.length > 0 && automationFollowupPresent(events, livePending)) {
|
|
2593
|
-
this.store.clearPendingFollowupIf(
|
|
2667
|
+
const cleared = this.store.clearPendingFollowupIf(
|
|
2594
2668
|
conversationId,
|
|
2595
2669
|
(m) => m.trim() === livePending
|
|
2596
2670
|
);
|
|
2671
|
+
if (cleared) {
|
|
2672
|
+
this.armAmbientChainAfterDeliveredFixTip(
|
|
2673
|
+
conversationId,
|
|
2674
|
+
livePending
|
|
2675
|
+
);
|
|
2676
|
+
}
|
|
2597
2677
|
return { commit: true, value: null };
|
|
2598
2678
|
}
|
|
2599
2679
|
try {
|
|
@@ -2608,10 +2688,13 @@ var ReviewEngine = class {
|
|
|
2608
2688
|
return { commit: true, value: null };
|
|
2609
2689
|
}
|
|
2610
2690
|
if (events.length > 0 && automationFollowupPresent(events, after)) {
|
|
2611
|
-
this.store.clearPendingFollowupIf(
|
|
2691
|
+
const cleared = this.store.clearPendingFollowupIf(
|
|
2612
2692
|
conversationId,
|
|
2613
2693
|
(m) => m.trim() === after
|
|
2614
2694
|
);
|
|
2695
|
+
if (cleared) {
|
|
2696
|
+
this.armAmbientChainAfterDeliveredFixTip(conversationId, after);
|
|
2697
|
+
}
|
|
2615
2698
|
return { commit: true, value: null };
|
|
2616
2699
|
}
|
|
2617
2700
|
return {
|
|
@@ -2666,15 +2749,45 @@ var ReviewEngine = class {
|
|
|
2666
2749
|
* Clear sticky code_edited so Stop→revert→resend cannot open a phantom fix
|
|
2667
2750
|
* chain on the next completed stop (disk may already be clean).
|
|
2668
2751
|
* Leave fix/confirm pending alone (delivery retry still valid if inject raced).
|
|
2669
|
-
*
|
|
2752
|
+
*
|
|
2753
|
+
* Project-scope ambient/planning: after recover soft-reset cleared
|
|
2754
|
+
* chain_pending, sticky code_edited may be the only handoff marker. Clearing
|
|
2755
|
+
* it without a freeze leaves fix_round residue that cannot E3 (bare fix_round
|
|
2756
|
+
* must not phantom-confirm). Freeze into confirm_left, or re-arm chain_pending
|
|
2757
|
+
* when an undelivered fix tip remains. Checklist executing keeps residue-E2.
|
|
2758
|
+
*
|
|
2759
|
+
* Clears + freeze share one exclusiveWrite so a mid-abort failure cannot leave
|
|
2670
2760
|
* recover gone while code_edited sticky (or the reverse).
|
|
2671
2761
|
*/
|
|
2672
2762
|
handleAbortedStop(session) {
|
|
2673
2763
|
try {
|
|
2674
2764
|
const cid2 = session.conversation_id;
|
|
2765
|
+
const ambientFreeze = this.config.reviewScope === "project" && !isChecklistExecuting(session);
|
|
2675
2766
|
this.store.exclusiveWrite(() => {
|
|
2676
2767
|
this.store.clearPendingFollowupIf(cid2, isRecoverOrStuckFollowupMessage);
|
|
2768
|
+
const chain = this.store.getReviewChain(cid2);
|
|
2769
|
+
const pending = chain?.pending_followup?.trim() ?? "";
|
|
2770
|
+
const fixPending = this.isFixFollowupMessage(pending);
|
|
2771
|
+
const mid = this.isMidConfirmOrE5(chain);
|
|
2772
|
+
const fixRound = chain?.fix_round ?? 0;
|
|
2773
|
+
const wasArmed = chain?.chain_pending === 1;
|
|
2677
2774
|
this.store.clearCodeEdited(cid2);
|
|
2775
|
+
if (ambientFreeze && !mid && fixRound > 0) {
|
|
2776
|
+
if (fixPending) {
|
|
2777
|
+
this.store.updateReviewChain(cid2, { chain_pending: 1 });
|
|
2778
|
+
} else if (!pending && wasArmed) {
|
|
2779
|
+
const rounds = this.config.confirmRounds;
|
|
2780
|
+
if (rounds > 0) {
|
|
2781
|
+
this.store.updateReviewChain(cid2, {
|
|
2782
|
+
confirm_left: rounds,
|
|
2783
|
+
chain_pending: 0,
|
|
2784
|
+
code_edited: 0
|
|
2785
|
+
});
|
|
2786
|
+
} else {
|
|
2787
|
+
this.store.updateReviewChain(cid2, { chain_pending: 1 });
|
|
2788
|
+
}
|
|
2789
|
+
}
|
|
2790
|
+
}
|
|
2678
2791
|
return { commit: true, value: void 0 };
|
|
2679
2792
|
});
|
|
2680
2793
|
} catch {
|
|
@@ -2860,7 +2973,10 @@ var ReviewEngine = class {
|
|
|
2860
2973
|
if (!stamp2) {
|
|
2861
2974
|
return { commit: false, value: { role: "failed" } };
|
|
2862
2975
|
}
|
|
2863
|
-
this.store.
|
|
2976
|
+
const liveRedeliver = this.store.getReviewChain(conversationId);
|
|
2977
|
+
if (liveRedeliver?.code_edited !== 1) {
|
|
2978
|
+
this.store.clearChainPending(conversationId);
|
|
2979
|
+
}
|
|
2864
2980
|
this.armRecoverClaimRedeliverHold(conversationId, debounceMs);
|
|
2865
2981
|
return {
|
|
2866
2982
|
commit: true,
|
|
@@ -2871,7 +2987,10 @@ var ReviewEngine = class {
|
|
|
2871
2987
|
this.applySoftResetAmbientChainForErrorRecover(conversationId);
|
|
2872
2988
|
const live = this.store.getReviewChain(conversationId);
|
|
2873
2989
|
if (fixTipAtClaim && live && !this.isMidConfirmOrE5(live)) {
|
|
2874
|
-
this.store.updateReviewChain(conversationId, {
|
|
2990
|
+
this.store.updateReviewChain(conversationId, {
|
|
2991
|
+
code_edited: 1,
|
|
2992
|
+
chain_pending: 1
|
|
2993
|
+
});
|
|
2875
2994
|
}
|
|
2876
2995
|
} else {
|
|
2877
2996
|
this.applyExecutingErrorRecoverChainAdjustments(conversationId, {
|
|
@@ -2885,7 +3004,14 @@ var ReviewEngine = class {
|
|
|
2885
3004
|
if (!stamp) {
|
|
2886
3005
|
return { commit: false, value: { role: "failed" } };
|
|
2887
3006
|
}
|
|
2888
|
-
|
|
3007
|
+
if (!ambient) {
|
|
3008
|
+
this.store.clearChainPending(conversationId);
|
|
3009
|
+
} else {
|
|
3010
|
+
const liveAfter = this.store.getReviewChain(conversationId);
|
|
3011
|
+
if (liveAfter?.code_edited !== 1) {
|
|
3012
|
+
this.store.clearChainPending(conversationId);
|
|
3013
|
+
}
|
|
3014
|
+
}
|
|
2889
3015
|
this.armRecoverClaimRedeliverHold(conversationId, debounceMs);
|
|
2890
3016
|
return {
|
|
2891
3017
|
commit: true,
|
|
@@ -3060,7 +3186,10 @@ var ReviewEngine = class {
|
|
|
3060
3186
|
if (!this.store.casBumpPendingFollowupAt(conversationId, expectedStamp)) {
|
|
3061
3187
|
return { commit: false, value: null };
|
|
3062
3188
|
}
|
|
3063
|
-
this.store.
|
|
3189
|
+
const afterBump = this.store.getReviewChain(conversationId);
|
|
3190
|
+
if (afterBump?.code_edited !== 1) {
|
|
3191
|
+
this.store.clearChainPending(conversationId);
|
|
3192
|
+
}
|
|
3064
3193
|
return {
|
|
3065
3194
|
commit: true,
|
|
3066
3195
|
value: {
|
|
@@ -3200,7 +3329,14 @@ var ReviewEngine = class {
|
|
|
3200
3329
|
if (!isRecoverFollowupMessage(live)) {
|
|
3201
3330
|
return { commit: false, value: null };
|
|
3202
3331
|
}
|
|
3203
|
-
|
|
3332
|
+
if (!ambientSoftReset) {
|
|
3333
|
+
this.store.clearChainPending(conversationId);
|
|
3334
|
+
} else {
|
|
3335
|
+
const liveChain = this.store.getReviewChain(conversationId);
|
|
3336
|
+
if (liveChain?.code_edited !== 1) {
|
|
3337
|
+
this.store.clearChainPending(conversationId);
|
|
3338
|
+
}
|
|
3339
|
+
}
|
|
3204
3340
|
return { commit: true, value: action };
|
|
3205
3341
|
});
|
|
3206
3342
|
try {
|
|
@@ -3236,14 +3372,20 @@ var ReviewEngine = class {
|
|
|
3236
3372
|
if (!isRecoverFollowupMessage(live)) {
|
|
3237
3373
|
return { commit: false, value: null };
|
|
3238
3374
|
}
|
|
3239
|
-
this.store.
|
|
3375
|
+
const liveChain = this.store.getReviewChain(conversationId);
|
|
3376
|
+
if (liveChain?.code_edited !== 1) {
|
|
3377
|
+
this.store.clearChainPending(conversationId);
|
|
3378
|
+
}
|
|
3240
3379
|
return { commit: true, value: action };
|
|
3241
3380
|
});
|
|
3242
3381
|
} catch {
|
|
3243
3382
|
}
|
|
3244
3383
|
this.emit(conversationId, action);
|
|
3245
3384
|
try {
|
|
3246
|
-
this.store.
|
|
3385
|
+
const liveChain = this.store.getReviewChain(conversationId);
|
|
3386
|
+
if (liveChain?.code_edited !== 1) {
|
|
3387
|
+
this.store.clearChainPending(conversationId);
|
|
3388
|
+
}
|
|
3247
3389
|
} catch {
|
|
3248
3390
|
}
|
|
3249
3391
|
try {
|
|
@@ -3331,7 +3473,8 @@ var ReviewEngine = class {
|
|
|
3331
3473
|
* do not regress to another fix. Ready-for-E3 requires empty pending (not
|
|
3332
3474
|
* merely !fixPending). Force code_edited only for an active fix
|
|
3333
3475
|
* (code_edited / undelivered fix pending / chain_pending with pending still
|
|
3334
|
-
* set).
|
|
3476
|
+
* set). Mid-fix resumeFix keeps chain_pending=1 so abort can freeze via
|
|
3477
|
+
* wasArmed; bare leftover fix_round stays disarmed (ambient phantom residue).
|
|
3335
3478
|
*/
|
|
3336
3479
|
applySoftResetAmbientChainForErrorRecover(conversationId) {
|
|
3337
3480
|
this.store.ensureReviewChain(conversationId);
|
|
@@ -3350,7 +3493,10 @@ var ReviewEngine = class {
|
|
|
3350
3493
|
this.store.softResetAmbientChainUnlessRecover(conversationId, {
|
|
3351
3494
|
confirm_left: atE5 || midConfirm ? chain.confirm_left : readyForE3 && rounds > 0 ? rounds : null,
|
|
3352
3495
|
item_confirm_complete: atE5 ? chain.item_confirm_complete : 0,
|
|
3353
|
-
chain_pending
|
|
3496
|
+
// Mid-fix resume keeps chain_pending so abort clearing code_edited still
|
|
3497
|
+
// has wasArmed handoff (freeze into confirm). Ready-for-E3 / idle residue
|
|
3498
|
+
// stay 0 — bare fix_round must not phantom-E3 after recover tip clears.
|
|
3499
|
+
chain_pending: resumeFix ? 1 : 0,
|
|
3354
3500
|
// Preserve an in-flight edit marker (E2 wins over E4); else force only for mid-fix.
|
|
3355
3501
|
code_edited: resumeFix || chain.code_edited === 1 ? 1 : 0
|
|
3356
3502
|
});
|
|
@@ -3360,6 +3506,51 @@ var ReviewEngine = class {
|
|
|
3360
3506
|
const line = firstSubstantiveLine(message) || message.trim();
|
|
3361
3507
|
return line.startsWith("Review fix") || line.startsWith("\u81EA\u5BA1\u4FEE\u590D");
|
|
3362
3508
|
}
|
|
3509
|
+
/**
|
|
3510
|
+
* Unlocked callers: clear snapshot needle + ambient E3 arm in one
|
|
3511
|
+
* exclusiveWrite. A crash mid-pair must not leave tip cleared with
|
|
3512
|
+
* chain_pending still 0 (silent ambient stall). Safe under an open writer
|
|
3513
|
+
* only via {@link armAmbientChainAfterDeliveredFixTip} after an inline clear
|
|
3514
|
+
* (clearPendingFollowupIf runs in-txn when writeDepth > 0).
|
|
3515
|
+
*/
|
|
3516
|
+
clearMatchingPendingAndArmAmbient(conversationId, pending) {
|
|
3517
|
+
try {
|
|
3518
|
+
return this.store.exclusiveWrite(() => {
|
|
3519
|
+
const cleared = this.store.clearPendingFollowupIf(
|
|
3520
|
+
conversationId,
|
|
3521
|
+
(m) => m.trim() === pending
|
|
3522
|
+
);
|
|
3523
|
+
if (cleared) {
|
|
3524
|
+
this.armAmbientChainAfterDeliveredFixTip(conversationId, pending);
|
|
3525
|
+
}
|
|
3526
|
+
return { commit: true, value: cleared };
|
|
3527
|
+
});
|
|
3528
|
+
} catch {
|
|
3529
|
+
return false;
|
|
3530
|
+
}
|
|
3531
|
+
}
|
|
3532
|
+
/**
|
|
3533
|
+
* After a delivered ambient fix tip is cleared, recover/abort may have left
|
|
3534
|
+
* chain_pending=0. Re-arm so this completed stop can E3 → confirm instead of
|
|
3535
|
+
* silent stall. Never arms bare stale fix_round without a delivered fix tip
|
|
3536
|
+
* (keeps F-ERR-AMBIENT-STALE-FIX-ROUND / F-ABORT-NO-PHANTOM-FIX).
|
|
3537
|
+
* Call under the same writer txn as the clear when possible — throws must
|
|
3538
|
+
* propagate so the clear can roll back. Still arms when code_edited=1 so a
|
|
3539
|
+
* concurrent abort clearing sticky edit keeps wasArmed handoff.
|
|
3540
|
+
*/
|
|
3541
|
+
armAmbientChainAfterDeliveredFixTip(conversationId, deliveredPending) {
|
|
3542
|
+
if (!this.isFixFollowupMessage(deliveredPending)) return;
|
|
3543
|
+
if (this.config.reviewScope !== "project") return;
|
|
3544
|
+
const session = this.store.getSession(conversationId);
|
|
3545
|
+
if (!session || isChecklistExecuting(session)) return;
|
|
3546
|
+
const chain = this.store.getReviewChain(conversationId);
|
|
3547
|
+
if (!chain || chain.fix_round <= 0) return;
|
|
3548
|
+
if (this.isMidConfirmOrE5(chain)) return;
|
|
3549
|
+
if (chain.chain_pending === 1) return;
|
|
3550
|
+
const live = chain.pending_followup?.trim() ?? "";
|
|
3551
|
+
if (live) return;
|
|
3552
|
+
this.store.updateReviewChain(conversationId, { chain_pending: 1 });
|
|
3553
|
+
}
|
|
3363
3554
|
/** Mid-confirm or E5-ready — must not phantom-arm code_edited over E4/E5. */
|
|
3364
3555
|
isMidConfirmOrE5(chain) {
|
|
3365
3556
|
if (!chain) return false;
|
|
@@ -3501,7 +3692,7 @@ var ReviewEngine = class {
|
|
|
3501
3692
|
return { commit: false, value: null };
|
|
3502
3693
|
}
|
|
3503
3694
|
const fresh = this.store.getReviewChain(cid2);
|
|
3504
|
-
if (!fresh || fresh.code_edited === 1 || fresh.confirm_left !== null || fresh.item_confirm_complete === 1 || fresh.chain_pending === 1 || fresh.fix_round > 0) {
|
|
3695
|
+
if (!fresh || fresh.code_edited === 1 || fresh.confirm_left !== null || fresh.item_confirm_complete === 1 || fresh.chain_pending === 1 || fresh.fix_round > 0 || isRecoverOrStuckFollowupMessage(fresh.pending_followup?.trim() ?? "")) {
|
|
3505
3696
|
return { commit: false, value: null };
|
|
3506
3697
|
}
|
|
3507
3698
|
const refreshed = this.parseSessionChecklist(lockedSession);
|
|
@@ -3613,7 +3804,7 @@ var ReviewEngine = class {
|
|
|
3613
3804
|
return { commit: false, value: null };
|
|
3614
3805
|
}
|
|
3615
3806
|
const fresh = this.store.getReviewChain(cid2);
|
|
3616
|
-
if (!fresh || fresh.code_edited === 1 || fresh.confirm_left !== null || fresh.item_confirm_complete === 1 || fresh.chain_pending === 1 || fresh.fix_round > 0) {
|
|
3807
|
+
if (!fresh || fresh.code_edited === 1 || fresh.confirm_left !== null || fresh.item_confirm_complete === 1 || fresh.chain_pending === 1 || fresh.fix_round > 0 || isRecoverOrStuckFollowupMessage(fresh.pending_followup?.trim() ?? "")) {
|
|
3617
3808
|
return { commit: false, value: null };
|
|
3618
3809
|
}
|
|
3619
3810
|
const refreshed = this.parseSessionChecklist(sess);
|
|
@@ -3740,6 +3931,10 @@ var ReviewEngine = class {
|
|
|
3740
3931
|
if (!fresh || fresh.code_edited !== 1) {
|
|
3741
3932
|
return { commit: false, value: null };
|
|
3742
3933
|
}
|
|
3934
|
+
const pendingLive = fresh.pending_followup?.trim() ?? "";
|
|
3935
|
+
if (isRecoverOrStuckFollowupMessage(pendingLive)) {
|
|
3936
|
+
return { commit: false, value: null };
|
|
3937
|
+
}
|
|
3743
3938
|
const fixRound = this.nextSessionRound(fresh);
|
|
3744
3939
|
const message = this.render("review.fix", { round: fixRound, total: rounds });
|
|
3745
3940
|
const out = {
|
|
@@ -3827,6 +4022,10 @@ var ReviewEngine = class {
|
|
|
3827
4022
|
if (!fresh || fresh.code_edited === 1 || fresh.confirm_left !== expectedLeft) {
|
|
3828
4023
|
return { commit: false, value: null };
|
|
3829
4024
|
}
|
|
4025
|
+
const pendingLive = fresh.pending_followup?.trim() ?? "";
|
|
4026
|
+
if (isRecoverOrStuckFollowupMessage(pendingLive)) {
|
|
4027
|
+
return { commit: false, value: null };
|
|
4028
|
+
}
|
|
3830
4029
|
const sessionRound = this.nextSessionRound(fresh);
|
|
3831
4030
|
const message = this.render(kind, {
|
|
3832
4031
|
n,
|
|
@@ -3906,6 +4105,10 @@ var ReviewEngine = class {
|
|
|
3906
4105
|
if (!atE5) {
|
|
3907
4106
|
return { commit: false, value: null };
|
|
3908
4107
|
}
|
|
4108
|
+
const pendingLive = fresh.pending_followup?.trim() ?? "";
|
|
4109
|
+
if (isRecoverOrStuckFollowupMessage(pendingLive)) {
|
|
4110
|
+
return { commit: false, value: null };
|
|
4111
|
+
}
|
|
3909
4112
|
const sess = this.store.getSession(cid2);
|
|
3910
4113
|
if (!sess || !isChecklistExecuting(sess)) {
|
|
3911
4114
|
return { commit: false, value: null };
|
|
@@ -3996,6 +4199,10 @@ var ReviewEngine = class {
|
|
|
3996
4199
|
if (!atE5) {
|
|
3997
4200
|
return { commit: false, value: null };
|
|
3998
4201
|
}
|
|
4202
|
+
const pendingLive = fresh.pending_followup?.trim() ?? "";
|
|
4203
|
+
if (isRecoverOrStuckFollowupMessage(pendingLive)) {
|
|
4204
|
+
return { commit: false, value: null };
|
|
4205
|
+
}
|
|
3999
4206
|
const lockedSession = this.store.getSession(cid2);
|
|
4000
4207
|
if (!lockedSession || !sessionReviewRunnable(lockedSession, this.config.reviewScope)) {
|
|
4001
4208
|
return { commit: false, value: null };
|
package/dist/init/types.d.ts
CHANGED
|
@@ -75,7 +75,7 @@ export interface HooksFile {
|
|
|
75
75
|
[event: string]: HookCommand[] | undefined;
|
|
76
76
|
};
|
|
77
77
|
}
|
|
78
|
-
export declare const PACKAGE_VERSION = "0.2.
|
|
78
|
+
export declare const PACKAGE_VERSION = "0.2.8";
|
|
79
79
|
export declare const HOOK_MARKER = "autopilot-harness";
|
|
80
80
|
export declare const AUTOPILOT_EVENTS: readonly ["beforeSubmitPrompt", "afterFileEdit", "stop"];
|
|
81
81
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/init/types.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@autopilot-harness/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8",
|
|
4
4
|
"description": "Autopilot harness CLI — structured planning, checklist execution, and multi-lens self-review for Cursor and Claude Code (bin: autopilot-harness)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -31,10 +31,10 @@
|
|
|
31
31
|
"@clack/prompts": "^0.10.0",
|
|
32
32
|
"commander": "^13.1.0",
|
|
33
33
|
"yaml": "^2.7.0",
|
|
34
|
-
"@autopilot-harness/core": "0.2.
|
|
35
|
-
"@autopilot-harness/i18n": "0.2.
|
|
36
|
-
"@autopilot-harness/port-
|
|
37
|
-
"@autopilot-harness/port-
|
|
34
|
+
"@autopilot-harness/core": "0.2.8",
|
|
35
|
+
"@autopilot-harness/i18n": "0.2.8",
|
|
36
|
+
"@autopilot-harness/port-cursor": "0.2.8",
|
|
37
|
+
"@autopilot-harness/port-claude-code": "0.2.8"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"esbuild": "^0.25.12",
|