From 6f29de1d44551f6a3c9a2988b02f71af2c51aaa8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 17 May 2026 15:52:00 +0000 Subject: [PATCH 1/4] Initial plan From bd585b3d3c5506da7e7963c303379e08b19f69d6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 17 May 2026 15:59:03 +0000 Subject: [PATCH 2/4] feat: add architecture guardrails command Agent-Logs-Url: https://github.com/tninja/ai-code-interface.el/sessions/9370ff3b-9d42-4c80-b855-e61b0f2455a4 Co-authored-by: tninja <714625+tninja@users.noreply.github.com> --- README.org | 1 + ai-code-discussion.el | 90 +++++++++++++++++++++++++++++++++ ai-code.el | 1 + test/test_ai-code-discussion.el | 82 ++++++++++++++++++++++++++++++ 4 files changed, 174 insertions(+) diff --git a/README.org b/README.org index afafb553..1cdd1877 100644 --- a/README.org +++ b/README.org @@ -152,6 +152,7 @@ Enable installation of packages from MELPA by adding an entry to package-archive - *Context-Aware Code Actions*: The menu exposes dedicated entries for changing code (`c`), implementing TODOs (`i`), asking questions (`q`), explaining code (`x`), sending free-form commands (``), and refreshing AI context (`@`). Each command automatically captures the surrounding function, region, or clipboard contents (via `C-u`) to keep prompts precise. - *Agile Development Workflows*: Use the refactoring navigator (`r`), the guided TDD cycle (`t`), and the pull/review diff helper (`v`) to keep AI-assisted work aligned with agile best practices. Prompt authoring is first-class through quick access to the prompt file (`p`), build/test helper (`b`), and AI-assisted shell/file execution (`!`). In prompt files, send the current block with `C-c C-c`. - *Productivity & Debugging Utilities*: Initialize project navigation assets (`.`), investigate exceptions (`e`), auto-fix Flycheck issues in scope (`f`), copy or open file paths formatted for prompts (`k`, `o`), generate MCP inspector commands (`m`), capture session notes straight into Org (`n`), dictate prompts with speech-to-text (`:`), and toggle desktop notifications (`N`) to get alerted when AI responses are ready in background sessions. +- *Repo Guardrails Capture*: Derive a concise architecture guardrails file for the current repository with `C-c a A`. The command creates or updates `.ai.code.files/architecture-guardrails.md` so future AI coding sessions can reuse practical module boundaries, dependency rules, and validation expectations. - *Seamless Prompt Management*: Open the prompt file via `ai-code-open-prompt-file` (stored under `.ai.code.files/.ai.code.prompt.org` by default), send regions with `ai-code-prompt-send-block`, and reuse prompt snippets via `yasnippet` to keep conversations organized. - *Interactive Chat & Context Tools*: Dedicated buffers hold long-running chats, automatically enriched with file paths, diffs, and history from Magit or Git commands for richer AI responses. - *AI-Assisted Bash Commands*: From Dired, shell, eshell, or vterm, run `C-c a !` and type natural-language commands prefixed with `:` (e.g., `:count lines of python code recursively`); the tool generates the shell command for review and executes it in a compile buffer. diff --git a/ai-code-discussion.el b/ai-code-discussion.el index 566e8495..846803a0 100644 --- a/ai-code-discussion.el +++ b/ai-code-discussion.el @@ -679,6 +679,96 @@ This value is used by `ai-code-take-notes' when suggesting where to store notes. "Content of the most recent AI output" "Default request text for `ai-code-take-notes'.") +(defconst ai-code-discussion--architecture-guardrails-file-name + "architecture-guardrails.md" + "File name for derived architecture guardrails.") + +(defconst ai-code-discussion--architecture-guardrails-template + (mapconcat #'identity + '("# Architecture Guardrails" + "" + "## Purpose" + "" + "## Important Modules / Areas" + "" + "## Dependency Rules" + "" + "## State and Ownership Rules" + "" + "## AI Change Rules" + "" + "## Required Validation" + "" + "## Notes and Uncertainties" + "") + "\n") + "Initial Markdown template for architecture guardrails.") + +(defun ai-code--architecture-guardrails-relative-path () + "Return the repo-relative path for the architecture guardrails file." + (concat ai-code-files-dir-name "/" + ai-code-discussion--architecture-guardrails-file-name)) + +(defun ai-code--architecture-guardrails-file-path () + "Return the absolute path for the architecture guardrails file." + (expand-file-name ai-code-discussion--architecture-guardrails-file-name + (ai-code--ensure-files-directory))) + +(defun ai-code--ensure-architecture-guardrails-file () + "Create the architecture guardrails file with a starter template if missing." + (let ((target-file (ai-code--architecture-guardrails-file-path))) + (unless (file-exists-p target-file) + (with-temp-file target-file + (insert ai-code-discussion--architecture-guardrails-template))) + target-file)) + +(defun ai-code--build-architecture-guardrails-prompt (git-root) + "Build the default prompt to derive architecture guardrails for GIT-ROOT." + (let ((relative-path (ai-code--architecture-guardrails-relative-path))) + (mapconcat + #'identity + (list "Derive a lightweight architecture guardrails document for this existing repository." + (format "Repository path: %s" git-root) + (format "Write or update @%s." relative-path) + "" + "Infer practical module boundaries, dependency rules, state ownership rules, and validation expectations from the current code, tests, docs, and filenames." + "Do not invent an ideal architecture." + "Do not force DDD, Hexagonal Architecture, or Clean Architecture onto the repository." + "Prefer simple, practical rules over abstract architecture theory." + "Mark uncertain conclusions clearly." + "Focus on what helps future AI coding sessions avoid breaking boundaries or introducing messy dependencies." + "Do not suggest large refactors unless clearly separated as optional future ideas." + "Keep it concise, practical, and small enough to reuse in future AI prompts." + "" + "Use this structure:" + "# Architecture Guardrails" + "" + "## Purpose" + "## Important Modules / Areas" + "## Dependency Rules" + "## State and Ownership Rules" + "## AI Change Rules" + "## Required Validation" + "## Notes and Uncertainties" + "" + "If the file already exists, refine it instead of rewriting unrelated guidance.") + "\n"))) + +;;;###autoload +(defun ai-code-derive-architecture-guardrails () + "Ask the current AI backend to derive repository architecture guardrails." + (interactive) + (let ((git-root (ai-code--git-root))) + (unless git-root + (user-error "Not in a git repository")) + (ai-code--ensure-architecture-guardrails-file) + (when-let ((final-prompt + (ai-code-read-string + "Prompt: " + (ai-code--build-architecture-guardrails-prompt git-root)))) + (ai-code--insert-prompt final-prompt) + (message "Requested architecture guardrails for %s" git-root)))) + (defun ai-code--get-note-candidates (default-note-file) "Get a list of candidate note files. DEFAULT-NOTE-FILE is included in the list. Visible org buffers are prioritized." diff --git a/ai-code.el b/ai-code.el index e9955735..973d56a1 100644 --- a/ai-code.el +++ b/ai-code.el @@ -461,6 +461,7 @@ Shows the current backend label to the right." ("P" "AI session checkpoint" ai-code-session-checkpoint) ("e" "Debug exception (C-u: clipboard)" ai-code-investigate-exception) ("f" "Fix Flycheck errors in scope" ai-code-flycheck-fix-errors-in-scope) + ("A" "Derive Architecture Guardrails" ai-code-derive-architecture-guardrails) ("k" "Copy Cur File Name (C-u: full)" ai-code-copy-buffer-file-name-to-clipboard) ;; ("o" "Open recent file (C-u: insert)" ai-code-git-repo-recent-modified-files) ("p" "Open prompt history file" ai-code-open-prompt-file) diff --git a/test/test_ai-code-discussion.el b/test/test_ai-code-discussion.el index 565e6aa2..55c70693 100644 --- a/test/test_ai-code-discussion.el +++ b/test/test_ai-code-discussion.el @@ -447,6 +447,88 @@ (ai-code-take-notes t) (should (equal captured-file "/tmp/project/.ai.code.files/test-notes.org"))))) +(ert-deftest ai-code-test-derive-architecture-guardrails-creates-template-and-prompt () + "Test `ai-code-derive-architecture-guardrails' initializes the Markdown file and prompt." + (let* ((tmp-root (make-temp-file "ai-code-guardrails" t)) + (target-file (expand-file-name ".ai.code.files/architecture-guardrails.md" tmp-root)) + captured-initial-prompt + captured-final-prompt) + (unwind-protect + (cl-letf (((symbol-function 'ai-code--git-root) + (lambda (&optional _dir) + tmp-root)) + ((symbol-function 'ai-code-read-string) + (lambda (prompt initial-input &optional _candidate-list) + (should (equal prompt "Prompt: ")) + (setq captured-initial-prompt initial-input) + initial-input)) + ((symbol-function 'ai-code--insert-prompt) + (lambda (prompt) + (setq captured-final-prompt prompt)))) + (ai-code-derive-architecture-guardrails) + (should (file-exists-p target-file)) + (with-temp-buffer + (insert-file-contents target-file) + (should (string-match-p (regexp-quote "# Architecture Guardrails") + (buffer-string))) + (should (string-match-p (regexp-quote "## Dependency Rules") + (buffer-string))) + (should (string-match-p (regexp-quote "## Required Validation") + (buffer-string)))) + (should (string-match-p (regexp-quote "Derive a lightweight architecture guardrails document") + captured-initial-prompt)) + (should (string-match-p (regexp-quote "current code, tests, docs, and filenames") + captured-initial-prompt)) + (should (string-match-p (regexp-quote "Do not invent an ideal architecture") + captured-initial-prompt)) + (should (string-match-p (regexp-quote "Keep it concise") + captured-initial-prompt)) + (should (string-match-p (regexp-quote "@.ai.code.files/architecture-guardrails.md") + captured-initial-prompt)) + (should (equal captured-final-prompt captured-initial-prompt))) + (ignore-errors (delete-directory tmp-root t))))) + +(ert-deftest ai-code-test-derive-architecture-guardrails-preserves-existing-file () + "Test `ai-code-derive-architecture-guardrails' does not overwrite an existing file." + (let* ((tmp-root (make-temp-file "ai-code-guardrails-existing" t)) + (files-dir (expand-file-name ".ai.code.files" tmp-root)) + (target-file (expand-file-name "architecture-guardrails.md" files-dir)) + (existing-content "# Existing guardrails\n")) + (unwind-protect + (progn + (make-directory files-dir t) + (with-temp-file target-file + (insert existing-content)) + (cl-letf (((symbol-function 'ai-code--git-root) + (lambda (&optional _dir) + tmp-root)) + ((symbol-function 'ai-code-read-string) + (lambda (_prompt initial-input &optional _candidate-list) + initial-input)) + ((symbol-function 'ai-code--insert-prompt) + (lambda (_prompt)))) + (ai-code-derive-architecture-guardrails)) + (with-temp-buffer + (insert-file-contents target-file) + (should (equal (buffer-string) existing-content)))) + (ignore-errors (delete-directory tmp-root t))))) + +(ert-deftest ai-code-test-derive-architecture-guardrails-errors-outside-git-repo () + "Test `ai-code-derive-architecture-guardrails' requires a git repository." + (cl-letf (((symbol-function 'ai-code--git-root) + (lambda (&optional _dir) + nil))) + (should-error (ai-code-derive-architecture-guardrails) + :type 'user-error))) + +(ert-deftest ai-code-test-menu-source-includes-derive-architecture-guardrails-entry () + "Test the menu source exposes the architecture guardrails command." + (with-temp-buffer + (insert-file-contents (expand-file-name "ai-code.el" default-directory)) + (should (re-search-forward + "(\"A\" \"Derive Architecture Guardrails\" ai-code-derive-architecture-guardrails)" + nil t)))) + (provide 'test_ai-code-discussion) ;;; test_ai-code-discussion.el ends here From 3d41e4d731a8779e28a9ba0b3daafdcbf4ddf658 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 17 May 2026 16:00:09 +0000 Subject: [PATCH 3/4] test: tighten guardrails command coverage Agent-Logs-Url: https://github.com/tninja/ai-code-interface.el/sessions/9370ff3b-9d42-4c80-b855-e61b0f2455a4 Co-authored-by: tninja <714625+tninja@users.noreply.github.com> --- ai-code-discussion.el | 14 +++++++------ test/test_ai-code-discussion.el | 37 ++++++++++++++++++++++++++++----- 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/ai-code-discussion.el b/ai-code-discussion.el index 846803a0..2cca6986 100644 --- a/ai-code-discussion.el +++ b/ai-code-discussion.el @@ -762,12 +762,14 @@ This value is used by `ai-code-take-notes' when suggesting where to store notes. (unless git-root (user-error "Not in a git repository")) (ai-code--ensure-architecture-guardrails-file) - (when-let ((final-prompt - (ai-code-read-string - "Prompt: " - (ai-code--build-architecture-guardrails-prompt git-root)))) - (ai-code--insert-prompt final-prompt) - (message "Requested architecture guardrails for %s" git-root)))) + (if-let ((final-prompt + (ai-code-read-string + "Prompt: " + (ai-code--build-architecture-guardrails-prompt git-root)))) + (progn + (ai-code--insert-prompt final-prompt) + (message "Requested architecture guardrails for %s" git-root)) + (message "Architecture guardrails request cancelled")))) (defun ai-code--get-note-candidates (default-note-file) "Get a list of candidate note files. diff --git a/test/test_ai-code-discussion.el b/test/test_ai-code-discussion.el index 55c70693..3dab5557 100644 --- a/test/test_ai-code-discussion.el +++ b/test/test_ai-code-discussion.el @@ -521,13 +521,40 @@ (should-error (ai-code-derive-architecture-guardrails) :type 'user-error))) +(ert-deftest ai-code-test-derive-architecture-guardrails-reports-cancelled-request () + "Test `ai-code-derive-architecture-guardrails' reports cancellation." + (let* ((tmp-root (make-temp-file "ai-code-guardrails-cancel" t)) + captured-message + insert-called) + (unwind-protect + (cl-letf (((symbol-function 'ai-code--git-root) + (lambda (&optional _dir) + tmp-root)) + ((symbol-function 'ai-code-read-string) + (lambda (&rest _args) + nil)) + ((symbol-function 'ai-code--insert-prompt) + (lambda (&rest _args) + (setq insert-called t))) + ((symbol-function 'message) + (lambda (format-string &rest args) + (setq captured-message + (apply #'format format-string args))))) + (ai-code-derive-architecture-guardrails) + (should-not insert-called) + (should (equal captured-message + "Architecture guardrails request cancelled"))) + (ignore-errors (delete-directory tmp-root t))))) + (ert-deftest ai-code-test-menu-source-includes-derive-architecture-guardrails-entry () "Test the menu source exposes the architecture guardrails command." - (with-temp-buffer - (insert-file-contents (expand-file-name "ai-code.el" default-directory)) - (should (re-search-forward - "(\"A\" \"Derive Architecture Guardrails\" ai-code-derive-architecture-guardrails)" - nil t)))) + (let ((repo-root + (file-name-directory (locate-library "ai-code-discussion")))) + (with-temp-buffer + (insert-file-contents (expand-file-name "ai-code.el" repo-root)) + (should (re-search-forward + "(\"A\" \"Derive Architecture Guardrails\" ai-code-derive-architecture-guardrails)" + nil t))))) (provide 'test_ai-code-discussion) From 2dc0081fd6de843cc123be16d4bfb9e238878d02 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 17 May 2026 16:12:42 +0000 Subject: [PATCH 4/4] refactor: store architecture guardrails as org Agent-Logs-Url: https://github.com/tninja/ai-code-interface.el/sessions/9322736a-d00b-4e20-b59e-c90c9286ebe7 Co-authored-by: tninja <714625+tninja@users.noreply.github.com> --- README.org | 2 +- ai-code-discussion.el | 79 ++++++++++++++++++--------------- test/test_ai-code-discussion.el | 20 +++++---- 3 files changed, 56 insertions(+), 45 deletions(-) diff --git a/README.org b/README.org index 1cdd1877..c4f8cabd 100644 --- a/README.org +++ b/README.org @@ -152,7 +152,7 @@ Enable installation of packages from MELPA by adding an entry to package-archive - *Context-Aware Code Actions*: The menu exposes dedicated entries for changing code (`c`), implementing TODOs (`i`), asking questions (`q`), explaining code (`x`), sending free-form commands (``), and refreshing AI context (`@`). Each command automatically captures the surrounding function, region, or clipboard contents (via `C-u`) to keep prompts precise. - *Agile Development Workflows*: Use the refactoring navigator (`r`), the guided TDD cycle (`t`), and the pull/review diff helper (`v`) to keep AI-assisted work aligned with agile best practices. Prompt authoring is first-class through quick access to the prompt file (`p`), build/test helper (`b`), and AI-assisted shell/file execution (`!`). In prompt files, send the current block with `C-c C-c`. - *Productivity & Debugging Utilities*: Initialize project navigation assets (`.`), investigate exceptions (`e`), auto-fix Flycheck issues in scope (`f`), copy or open file paths formatted for prompts (`k`, `o`), generate MCP inspector commands (`m`), capture session notes straight into Org (`n`), dictate prompts with speech-to-text (`:`), and toggle desktop notifications (`N`) to get alerted when AI responses are ready in background sessions. -- *Repo Guardrails Capture*: Derive a concise architecture guardrails file for the current repository with `C-c a A`. The command creates or updates `.ai.code.files/architecture-guardrails.md` so future AI coding sessions can reuse practical module boundaries, dependency rules, and validation expectations. +- *Repo Guardrails Capture*: Derive a concise architecture guardrails file for the current repository with `C-c a A`. The command creates or updates `.ai.code.files/architecture/guardrails.org` so future AI coding sessions can reuse practical module boundaries, dependency rules, and validation expectations. - *Seamless Prompt Management*: Open the prompt file via `ai-code-open-prompt-file` (stored under `.ai.code.files/.ai.code.prompt.org` by default), send regions with `ai-code-prompt-send-block`, and reuse prompt snippets via `yasnippet` to keep conversations organized. - *Interactive Chat & Context Tools*: Dedicated buffers hold long-running chats, automatically enriched with file paths, diffs, and history from Magit or Git commands for richer AI responses. - *AI-Assisted Bash Commands*: From Dired, shell, eshell, or vterm, run `C-c a !` and type natural-language commands prefixed with `:` (e.g., `:count lines of python code recursively`); the tool generates the shell command for review and executes it in a compile buffer. diff --git a/ai-code-discussion.el b/ai-code-discussion.el index 2cca6986..8b741fd1 100644 --- a/ai-code-discussion.el +++ b/ai-code-discussion.el @@ -680,43 +680,52 @@ This value is used by `ai-code-take-notes' when suggesting where to store notes. "Default request text for `ai-code-take-notes'.") (defconst ai-code-discussion--architecture-guardrails-file-name - "architecture-guardrails.md" + "guardrails.org" "File name for derived architecture guardrails.") +(defconst ai-code-discussion--architecture-guardrails-directory-name + "architecture" + "Directory name for derived architecture guardrails.") + (defconst ai-code-discussion--architecture-guardrails-template (mapconcat #'identity - '("# Architecture Guardrails" + '("#+TITLE: Architecture Guardrails" "" - "## Purpose" + "* Purpose" "" - "## Important Modules / Areas" + "* Important Modules / Areas" "" - "## Dependency Rules" + "* Dependency Rules" "" - "## State and Ownership Rules" + "* State and Ownership Rules" "" - "## AI Change Rules" + "* AI Change Rules" "" - "## Required Validation" + "* Required Validation" "" - "## Notes and Uncertainties" + "* Notes and Uncertainties" "") "\n") - "Initial Markdown template for architecture guardrails.") + "Initial Org template for architecture guardrails.") (defun ai-code--architecture-guardrails-relative-path () "Return the repo-relative path for the architecture guardrails file." (concat ai-code-files-dir-name "/" + ai-code-discussion--architecture-guardrails-directory-name "/" ai-code-discussion--architecture-guardrails-file-name)) (defun ai-code--architecture-guardrails-file-path () "Return the absolute path for the architecture guardrails file." (expand-file-name ai-code-discussion--architecture-guardrails-file-name - (ai-code--ensure-files-directory))) + (expand-file-name + ai-code-discussion--architecture-guardrails-directory-name + (ai-code--ensure-files-directory)))) (defun ai-code--ensure-architecture-guardrails-file () "Create the architecture guardrails file with a starter template if missing." (let ((target-file (ai-code--architecture-guardrails-file-path))) + (unless (file-directory-p (file-name-directory target-file)) + (make-directory (file-name-directory target-file) t)) (unless (file-exists-p target-file) (with-temp-file target-file (insert ai-code-discussion--architecture-guardrails-template))) @@ -728,30 +737,30 @@ This value is used by `ai-code-take-notes' when suggesting where to store notes. (mapconcat #'identity (list "Derive a lightweight architecture guardrails document for this existing repository." - (format "Repository path: %s" git-root) - (format "Write or update @%s." relative-path) - "" - "Infer practical module boundaries, dependency rules, state ownership rules, and validation expectations from the current code, tests, docs, and filenames." - "Do not invent an ideal architecture." - "Do not force DDD, Hexagonal Architecture, or Clean Architecture onto the repository." - "Prefer simple, practical rules over abstract architecture theory." - "Mark uncertain conclusions clearly." - "Focus on what helps future AI coding sessions avoid breaking boundaries or introducing messy dependencies." - "Do not suggest large refactors unless clearly separated as optional future ideas." - "Keep it concise, practical, and small enough to reuse in future AI prompts." - "" - "Use this structure:" - "# Architecture Guardrails" - "" - "## Purpose" - "## Important Modules / Areas" - "## Dependency Rules" - "## State and Ownership Rules" - "## AI Change Rules" - "## Required Validation" - "## Notes and Uncertainties" - "" - "If the file already exists, refine it instead of rewriting unrelated guidance.") + (format "Repository path: %s" git-root) + (format "Write or update @%s in Org-mode format." relative-path) + "" + "Infer practical module boundaries, dependency rules, state ownership rules, and validation expectations from the current code, tests, docs, and filenames." + "Do not invent an ideal architecture." + "Do not force DDD, Hexagonal Architecture, or Clean Architecture onto the repository." + "Prefer simple, practical rules over abstract architecture theory." + "Mark uncertain conclusions clearly." + "Focus on what helps future AI coding sessions avoid breaking boundaries or introducing messy dependencies." + "Do not suggest large refactors unless clearly separated as optional future ideas." + "Keep it concise, practical, and small enough to reuse in future AI prompts." + "" + "Use this Org structure:" + "#+TITLE: Architecture Guardrails" + "" + "* Purpose" + "* Important Modules / Areas" + "* Dependency Rules" + "* State and Ownership Rules" + "* AI Change Rules" + "* Required Validation" + "* Notes and Uncertainties" + "" + "If the file already exists, refine it instead of rewriting unrelated guidance.") "\n"))) ;;;###autoload diff --git a/test/test_ai-code-discussion.el b/test/test_ai-code-discussion.el index 3dab5557..72973ead 100644 --- a/test/test_ai-code-discussion.el +++ b/test/test_ai-code-discussion.el @@ -448,9 +448,9 @@ (should (equal captured-file "/tmp/project/.ai.code.files/test-notes.org"))))) (ert-deftest ai-code-test-derive-architecture-guardrails-creates-template-and-prompt () - "Test `ai-code-derive-architecture-guardrails' initializes the Markdown file and prompt." + "Test `ai-code-derive-architecture-guardrails' initializes the Org file and prompt." (let* ((tmp-root (make-temp-file "ai-code-guardrails" t)) - (target-file (expand-file-name ".ai.code.files/architecture-guardrails.md" tmp-root)) + (target-file (expand-file-name ".ai.code.files/architecture/guardrails.org" tmp-root)) captured-initial-prompt captured-final-prompt) (unwind-protect @@ -469,11 +469,11 @@ (should (file-exists-p target-file)) (with-temp-buffer (insert-file-contents target-file) - (should (string-match-p (regexp-quote "# Architecture Guardrails") + (should (string-match-p (regexp-quote "#+TITLE: Architecture Guardrails") (buffer-string))) - (should (string-match-p (regexp-quote "## Dependency Rules") + (should (string-match-p (regexp-quote "* Dependency Rules") (buffer-string))) - (should (string-match-p (regexp-quote "## Required Validation") + (should (string-match-p (regexp-quote "* Required Validation") (buffer-string)))) (should (string-match-p (regexp-quote "Derive a lightweight architecture guardrails document") captured-initial-prompt)) @@ -483,7 +483,9 @@ captured-initial-prompt)) (should (string-match-p (regexp-quote "Keep it concise") captured-initial-prompt)) - (should (string-match-p (regexp-quote "@.ai.code.files/architecture-guardrails.md") + (should (string-match-p (regexp-quote "@.ai.code.files/architecture/guardrails.org") + captured-initial-prompt)) + (should (string-match-p (regexp-quote "Org-mode format") captured-initial-prompt)) (should (equal captured-final-prompt captured-initial-prompt))) (ignore-errors (delete-directory tmp-root t))))) @@ -491,9 +493,9 @@ (ert-deftest ai-code-test-derive-architecture-guardrails-preserves-existing-file () "Test `ai-code-derive-architecture-guardrails' does not overwrite an existing file." (let* ((tmp-root (make-temp-file "ai-code-guardrails-existing" t)) - (files-dir (expand-file-name ".ai.code.files" tmp-root)) - (target-file (expand-file-name "architecture-guardrails.md" files-dir)) - (existing-content "# Existing guardrails\n")) + (files-dir (expand-file-name ".ai.code.files/architecture" tmp-root)) + (target-file (expand-file-name "guardrails.org" files-dir)) + (existing-content "#+TITLE: Existing guardrails\n")) (unwind-protect (progn (make-directory files-dir t)