Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions ai-code.el
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,21 @@ ARG is the prefix argument."
ai-code-session-checkpoint-prompt)))
(ai-code--insert-prompt prompt)))

;;;###autoload
(defun ai-code-cli-resume-with-session-checkpoint (&optional arg prompt-for-checkpoint)
"Resume the current backend's CLI session and optionally request a checkpoint.
Argument ARG is passed to `ai-code-cli-resume'; with a prefix argument
\\[universal-argument], it is non-nil and preserves the backend's
interactive resume behavior.
PROMPT-FOR-CHECKPOINT is non-nil for interactive calls that should ask
whether to print a checkpoint after resuming. Noninteractive callers
normally omit it, which skips the prompt."
(interactive (list current-prefix-arg t))
(ai-code-cli-resume arg)
(when (and prompt-for-checkpoint
(y-or-n-p "Print AI session checkpoint? "))
(ai-code-session-checkpoint)))
Comment on lines +276 to +279

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Delay checkpoint until resume picker finishes

For picker-based resume flows, confirming here sends the checkpoint before the session has actually been chosen. For example, ai-code-opencode-resume documents that the CLI presents an interactive list of past sessions and then calls ai-code-backends-infra--cli-show-resume-picker (ai-code-opencode.el lines 85-100), and GitHub Copilot does the same picker poke (ai-code-github-copilot-cli.el lines 119-122). Because this wrapper asks immediately after ai-code-cli-resume returns, the checkpoint prompt is typed into the terminal picker instead of an active resumed AI prompt, so the new integrated checkpoint flow fails for those backends.

Useful? React with 👍 / 👎.


(defun ai-code--emacs-runtime-debug-prompt (description eval-available-p
&optional region-text
region-location-info
Expand Down Expand Up @@ -498,7 +513,7 @@ Shows the current backend label to the right."
;; Mirror aider.el's reusable-section approach using `transient-define-group`.
(transient-define-group ai-code--menu-ai-cli-session
("a" "Start AI CLI (C-u: args)" ai-code-cli-start)
("R" "Resume AI CLI (C-u: args)" ai-code-cli-resume)
("R" "Resume AI CLI (C-u: args)" ai-code-cli-resume-with-session-checkpoint)
("z" "Switch to AI CLI (C-u: hide)" ai-code-cli-switch-to-buffer-or-hide)
("s" ai-code-select-backend :description ai-code--select-backend-description)
("j" "Session dashboard" ai-code-session-dashboard)
Expand Down Expand Up @@ -538,7 +553,6 @@ Shows the current backend label to the right."
(transient-define-group ai-code--menu-other-tools
(ai-code--infix-toggle-auto-follow-up)
("." "Init projectile and gtags" ai-code-init-project)
("P" "AI session checkpoint" ai-code-session-checkpoint)
("e" "Investigate exception (C-u: clipboard)" ai-code-investigate-exception)
("f" "Fix Flycheck errors in scope" ai-code-flycheck-fix-errors-in-scope)
("k" "Copy Cur File Name (C-u: full)" ai-code-copy-buffer-file-name-to-clipboard)
Expand Down
60 changes: 50 additions & 10 deletions test/test_ai-code.el
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,9 @@
(lambda () 42))
((symbol-function 'buffer-substring-no-properties)
(lambda (_beg _end)
"(define-key test-map (kbd \"C-c x\") #'broken-command)"))
(if t
"(define-key test-map (kbd \"C-c x\") #'broken-command)"
nil)))
Comment on lines 227 to +231
((symbol-function 'ai-code--get-region-location-info)
(lambda (_beg _end)
"ai-code.el#L10-L11"))
Expand Down Expand Up @@ -297,6 +299,15 @@
(should (equal (plist-get (cdr suffix) :description)
"Session dashboard"))))

(ert-deftest ai-code-test-menu-ai-cli-session-resume-uses-checkpoint-wrapper ()
"Test that Resume AI CLI routes through the checkpoint-aware wrapper."
(let ((suffix (transient-get-suffix 'ai-code--menu-ai-cli-session "R")))
(should suffix)
(should (eq (plist-get (cdr suffix) :command)
'ai-code-cli-resume-with-session-checkpoint))
(should (equal (plist-get (cdr suffix) :description)
"Resume AI CLI (C-u: args)"))))

(ert-deftest ai-code-test-menu-other-tools-includes-debug-emacs-runtime-entry ()
"Test that the Other Tools menu exposes Emacs runtime debugging."
(let ((suffix (transient-get-suffix 'ai-code--menu-other-tools "d")))
Expand Down Expand Up @@ -334,15 +345,44 @@
(equal inserted-prompt
"Please stop and output a CHECKPOINT:\n- Goal\n- Files changed\n- Current hypothesis\n- Tests/build result\n- Blockers\n- Recommended next action\nDo not continue editing after this checkpoint"))))

(ert-deftest ai-code-test-menu-other-tools-includes-session-checkpoint-entry ()
"Test that the Other Tools menu exposes AI session checkpoint."
(let* ((suffix (transient-get-suffix 'ai-code--menu-other-tools "P"))
(definition (cdr suffix)))
(should suffix)
(should (eq (plist-get definition :command)
'ai-code-session-checkpoint))
(should (equal (plist-get definition :description)
"AI session checkpoint"))))
(ert-deftest ai-code-test-cli-resume-with-session-checkpoint-prompts-and-checkpoints ()
"Test that resume can immediately request a session checkpoint."
(let (resume-arg prompt-text checkpoint-called)
(cl-letf (((symbol-function 'ai-code-cli-resume)
(lambda (&optional arg)
(interactive "P")
(setq resume-arg arg)))
((symbol-function 'y-or-n-p)
(lambda (prompt)
(setq prompt-text prompt)
t))
((symbol-function 'ai-code-session-checkpoint)
(lambda ()
(setq checkpoint-called t))))
(let ((current-prefix-arg '(4)))
(call-interactively #'ai-code-cli-resume-with-session-checkpoint)))
(should (equal resume-arg '(4)))
(should (equal prompt-text "Print AI session checkpoint? "))
(should checkpoint-called)))

(ert-deftest ai-code-test-cli-resume-with-session-checkpoint-skips-checkpoint-when-declined ()
"Test that resume does not trigger a checkpoint when the user declines."
(let (checkpoint-called)
(cl-letf (((symbol-function 'ai-code-cli-resume)
(lambda (&optional _arg)
(interactive "P")))
((symbol-function 'y-or-n-p)
(lambda (_prompt) nil))
((symbol-function 'ai-code-session-checkpoint)
(lambda ()
(setq checkpoint-called t))))
(call-interactively #'ai-code-cli-resume-with-session-checkpoint))
(should-not checkpoint-called)))

(ert-deftest ai-code-test-menu-other-tools-removes-session-checkpoint-entry ()
"Test that the Other Tools menu no longer exposes a dedicated checkpoint item."
(should-not (ignore-errors
(transient-get-suffix 'ai-code--menu-other-tools "P"))))

(ert-deftest ai-code-test-menu-agile-development-includes-agent-handoff-entry ()
"Test that the agile menu exposes agent handoff."
Expand Down
Loading