ace-retro 0.16.0

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.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/.ace-defaults/nav/protocols/wfi-sources/ace-retro.yml +19 -0
  3. data/.ace-defaults/retro/config.yml +16 -0
  4. data/CHANGELOG.md +252 -0
  5. data/LICENSE +21 -0
  6. data/README.md +40 -0
  7. data/Rakefile +13 -0
  8. data/docs/demo/ace-retro-getting-started.gif +0 -0
  9. data/docs/demo/ace-retro-getting-started.tape.yml +33 -0
  10. data/docs/demo/fixtures/README.md +3 -0
  11. data/docs/demo/fixtures/sample.txt +1 -0
  12. data/docs/getting-started.md +77 -0
  13. data/docs/handbook.md +60 -0
  14. data/docs/usage.md +141 -0
  15. data/exe/ace-retro +22 -0
  16. data/handbook/skills/as-handbook-selfimprove/SKILL.md +31 -0
  17. data/handbook/skills/as-retro-create/SKILL.md +26 -0
  18. data/handbook/skills/as-retro-synthesize/SKILL.md +26 -0
  19. data/handbook/templates/retro/retro.template.md +194 -0
  20. data/handbook/workflow-instructions/retro/create.wf.md +141 -0
  21. data/handbook/workflow-instructions/retro/selfimprove.wf.md +197 -0
  22. data/handbook/workflow-instructions/retro/synthesize.wf.md +94 -0
  23. data/lib/ace/retro/atoms/retro_file_pattern.rb +40 -0
  24. data/lib/ace/retro/atoms/retro_frontmatter_defaults.rb +42 -0
  25. data/lib/ace/retro/atoms/retro_id_formatter.rb +37 -0
  26. data/lib/ace/retro/atoms/retro_validation_rules.rb +82 -0
  27. data/lib/ace/retro/cli/commands/create.rb +87 -0
  28. data/lib/ace/retro/cli/commands/doctor.rb +204 -0
  29. data/lib/ace/retro/cli/commands/list.rb +63 -0
  30. data/lib/ace/retro/cli/commands/show.rb +55 -0
  31. data/lib/ace/retro/cli/commands/update.rb +117 -0
  32. data/lib/ace/retro/cli.rb +70 -0
  33. data/lib/ace/retro/models/retro.rb +40 -0
  34. data/lib/ace/retro/molecules/retro_config_loader.rb +93 -0
  35. data/lib/ace/retro/molecules/retro_creator.rb +165 -0
  36. data/lib/ace/retro/molecules/retro_display_formatter.rb +95 -0
  37. data/lib/ace/retro/molecules/retro_doctor_fixer.rb +404 -0
  38. data/lib/ace/retro/molecules/retro_doctor_reporter.rb +257 -0
  39. data/lib/ace/retro/molecules/retro_frontmatter_validator.rb +120 -0
  40. data/lib/ace/retro/molecules/retro_loader.rb +119 -0
  41. data/lib/ace/retro/molecules/retro_mover.rb +80 -0
  42. data/lib/ace/retro/molecules/retro_resolver.rb +57 -0
  43. data/lib/ace/retro/molecules/retro_scanner.rb +56 -0
  44. data/lib/ace/retro/molecules/retro_structure_validator.rb +193 -0
  45. data/lib/ace/retro/organisms/retro_doctor.rb +199 -0
  46. data/lib/ace/retro/organisms/retro_manager.rb +210 -0
  47. data/lib/ace/retro/version.rb +7 -0
  48. data/lib/ace/retro.rb +41 -0
  49. metadata +165 -0
@@ -0,0 +1,197 @@
1
+ ---
2
+ doc-type: workflow
3
+ title: Self-Improve Workflow
4
+ purpose: Documentation for ace-retro/handbook/workflow-instructions/retro/selfimprove.wf.md
5
+ ace-docs:
6
+ last-updated: 2026-03-01
7
+ last-checked: 2026-03-21
8
+ ---
9
+
10
+ # Self-Improve Workflow
11
+
12
+ ## Goal
13
+
14
+ Transform mistakes and recurring issues into system improvements. Fix the process first, then fix the immediate issue.
15
+
16
+ ## Anti-Pattern
17
+
18
+ ❌ Mistake happens → Agent re-runs instruction → Same mistake can happen again
19
+
20
+ ## Correct Pattern
21
+
22
+ ✅ Mistake identified → Analyze root cause → Update process → Fix immediate issue → Record retro
23
+
24
+ ## Input Sources
25
+
26
+ Self-improvement is always a consequence of retrospective. Input can come from:
27
+
28
+ - **Session context** — analyze current conversation for mistakes or suboptimal patterns
29
+ - **Existing retros** — load retros via `ace-retro list`/`ace-retro show` to find recurring issues
30
+ - **User input** — user describes what went wrong
31
+
32
+ ## Process Steps
33
+
34
+ ### Step 1: Gather Input
35
+
36
+ Determine the source and capture incident details:
37
+
38
+ **From session context:**
39
+ - Review the current conversation for mistakes, repeated attempts, or corrections
40
+ - Identify what went wrong and what should have happened
41
+
42
+ **From existing retros:**
43
+ ```bash
44
+ # Find retros with relevant issues
45
+ ace-retro list --status active
46
+
47
+ # Load specific retro content
48
+ ace-retro show REF --content
49
+ ```
50
+
51
+ **From user input:**
52
+ - Capture the user's description of the problem
53
+
54
+ Document the incident:
55
+
56
+ | Question | Details |
57
+ |----------|---------|
58
+ | **What happened** | What action was taken? |
59
+ | **Actual result** | What was the output? |
60
+ | **Expected result** | What should have happened? |
61
+ | **Source** | Session / retro REF / user description |
62
+
63
+ ### Step 2: Identify Root Cause Category
64
+
65
+ Ask: "Why did this happen?" Categorize the root cause:
66
+
67
+ | Category | Description | Example |
68
+ |----------|-------------|---------|
69
+ | **Ambiguous instructions** | Workflow allows misinterpretation | "Reorganize commits" without specifying scope source |
70
+ | **Missing validation** | No checkpoint to catch the error | No step to verify scope before executing |
71
+ | **Assumed context** | Agent didn't have necessary information | Agent used plan data instead of querying actual state |
72
+ | **Scope narrowing** | Agent under-scoped the task | Followed plan literally instead of understanding intent |
73
+ | **Scope creep** | Agent over-scoped the task | Made changes beyond what was requested |
74
+ | **Missing example** | No example of correct behavior | Workflow lacks example showing full scope discovery |
75
+ | **Redundant computation** | Multiple agents derive same value independently, causing divergence | Orchestrator computes path one way, agent re-derives differently |
76
+
77
+ ### Step 3: Find the Source
78
+
79
+ Search for the relevant process files that need updating:
80
+
81
+ ```bash
82
+ # Search workflow instructions
83
+ ace-bundle wfi://{relevant-workflow}
84
+
85
+ # Search guides
86
+ ace-bundle guide://{relevant-guide}
87
+
88
+ # Search skills
89
+ ace-bundle skill://{relevant-skill}
90
+
91
+ # Discover available resources
92
+ ace-nav --sources
93
+ ```
94
+
95
+ **Search targets (in preference order):**
96
+
97
+ 1. **Workflow instructions** (`wfi://namespace/action`) — preferred for process improvements
98
+ 2. **Guides** (`guide://topic`) — preferred for best practices and conventions
99
+ 3. **Skills** (`.claude/skills/*/SKILL.md`) — only when workflow/guide doesn't exist
100
+ 4. **CLAUDE.md files** — project-level overrides only
101
+
102
+ ### Step 4: Draft the Fix
103
+
104
+ Propose specific edits. The fix should:
105
+
106
+ 1. **Address the root cause** — not just the symptom
107
+ 2. **Be minimal** — only change what's necessary
108
+ 3. **Include validation** — add checkpoints where missing
109
+ 4. **Add examples** — show correct behavior if unclear
110
+
111
+ **Fix templates by category:**
112
+
113
+ **For ambiguous instructions:**
114
+ ```markdown
115
+ ## After
116
+ **Scope Discovery**: Before executing, always query the actual state:
117
+ - Run the relevant query command to get the full scope
118
+ - Do NOT rely on estimates — query actual state
119
+ - Confirm scope with user if actual differs from expectations
120
+ ```
121
+
122
+ **For missing validation:**
123
+ ```markdown
124
+ ## After
125
+ ### Validate Before Executing
126
+ - [ ] Query actual state
127
+ - [ ] Compare to expected scope
128
+ - [ ] If mismatch, confirm with user before proceeding
129
+ ```
130
+
131
+ **For redundant computation:**
132
+ ```markdown
133
+ ## After
134
+ Pass computed values explicitly; don't re-derive:
135
+ - Orchestrator computes once and passes to subagent
136
+ - Subagent uses the provided value, never re-derives
137
+ ```
138
+
139
+ ### Step 5: Present to User
140
+
141
+ Before making any changes, present:
142
+
143
+ ```markdown
144
+ ## Root Cause Analysis
145
+
146
+ **What happened**: [Concise description]
147
+ **Why it happened**: [Root cause category and explanation]
148
+ **Source file**: [File path(s) to update]
149
+
150
+ ## Proposed Process Changes
151
+
152
+ **File**: `{path/to/file}`
153
+ **Change**: [Description]
154
+
155
+ **Diff preview**:
156
+ ` ``diff
157
+ - [old content]
158
+ + [new content]
159
+ ` ``
160
+
161
+ ## Questions
162
+
163
+ 1. Does this analysis match your understanding?
164
+ 2. Should I proceed with these process changes?
165
+ 3. After updating the process, should I also fix the immediate issue?
166
+ ```
167
+
168
+ ### Step 6: Implement Changes
169
+
170
+ After user approval:
171
+
172
+ 1. **Update the process file(s)** — apply the proposed edits
173
+ 2. **Fix the immediate issue** (if requested)
174
+ 3. **Record a retro** documenting the improvement:
175
+
176
+ ```bash
177
+ ace-retro create "selfimprove-TOPIC" --type self-improvement --tags process-fix
178
+ ```
179
+
180
+ Populate the retro with the root cause analysis, the fix applied, and the expected impact.
181
+
182
+ ### Step 7: Archive Consumed Retros
183
+
184
+ If the input source was an existing retro, archive it after the improvement has been applied — the retro has been "consumed":
185
+
186
+ ```bash
187
+ ace-retro move REF --to archive
188
+ ```
189
+
190
+ ## Success Criteria
191
+
192
+ - Root cause is identified (not just symptoms)
193
+ - Process fix prevents recurrence
194
+ - User approves changes before implementation
195
+ - Both process and immediate issue are addressed
196
+ - Improvement is recorded as a retro via `ace-retro create`
197
+ - Source retros (if any) are archived after processing
@@ -0,0 +1,94 @@
1
+ ---
2
+ doc-type: workflow
3
+ title: Synthesize Retros Workflow Instruction
4
+ purpose: Documentation for ace-retro/handbook/workflow-instructions/retro/synthesize.wf.md
5
+ ace-docs:
6
+ last-updated: 2026-03-01
7
+ last-checked: 2026-03-21
8
+ ---
9
+
10
+ # Synthesize Retros Workflow Instruction
11
+
12
+ ## Goal
13
+
14
+ Reduce multiple retros into a single synthesis retro. Distill common themes, recurring issues, and shared action items from N input retros into one consolidated retro using the standard retro format.
15
+
16
+ ## Prerequisites
17
+
18
+ - At least 2 active retros exist to synthesize
19
+ - Access to `ace-retro` CLI
20
+
21
+ ## Process Steps
22
+
23
+ ### 1. Gather Retros
24
+
25
+ Find candidate retros for synthesis:
26
+
27
+ ```bash
28
+ # List active retros
29
+ ace-retro list --status active
30
+
31
+ # Filter by tags if synthesizing a specific topic
32
+ ace-retro list --status active --tags TAG
33
+ ```
34
+
35
+ Select which retros to include. Good candidates share a common theme, time period, or tag.
36
+
37
+ ### 2. Load Content
38
+
39
+ Read each selected retro:
40
+
41
+ ```bash
42
+ ace-retro show REF --content
43
+ ```
44
+
45
+ Collect the content from all selected retros before proceeding to analysis.
46
+
47
+ ### 3. Reduce
48
+
49
+ Analyze all input retros together. Identify:
50
+
51
+ - **Common themes** — issues or observations that appear across multiple retros
52
+ - **Recurring patterns** — problems or successes that repeat
53
+ - **Shared action items** — improvements suggested in multiple retros
54
+ - **Contradictions** — conflicting recommendations that need resolution
55
+ - **Unique insights** — one-off observations worth preserving
56
+
57
+ For each theme, note which source retros contributed to it and how frequently it appeared.
58
+
59
+ ### 4. Create Synthesis Retro
60
+
61
+ ```bash
62
+ ace-retro create "synthesis-TOPIC" --tags synthesis
63
+ ```
64
+
65
+ Read the created file path from the output.
66
+
67
+ ### 5. Populate
68
+
69
+ Fill the synthesis retro using the standard template format (`tmpl://retro/retro`). The content is distilled from the N input retros:
70
+
71
+ - **What Went Well** — patterns of success across multiple retros, validated approaches
72
+ - **What Could Be Improved** — recurring issues, systemic problems identified across retros
73
+ - **Key Learnings** — consolidated insights, with frequency noted where relevant
74
+ - **Action Items** — merged and deduplicated action items, prioritized by how often they appeared
75
+
76
+ When populating, reference source retros to provide traceability (e.g., "Identified in 3/5 retros").
77
+
78
+ ### 6. Archive Sources
79
+
80
+ After the synthesis retro is populated and complete, archive each source retro — they have been "consumed" by the synthesis:
81
+
82
+ ```bash
83
+ ace-retro move REF --to archive
84
+ ```
85
+
86
+ Repeat for each source retro.
87
+
88
+ ## Success Criteria
89
+
90
+ - Synthesis retro created using standard retro format
91
+ - Common themes and recurring patterns identified across inputs
92
+ - Action items deduplicated and prioritized by frequency
93
+ - Source retros archived after processing
94
+ - Output is a single retro that stands on its own — no external templates or analytics needed
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ace
4
+ module Retro
5
+ module Atoms
6
+ # Provides glob patterns for finding retro files.
7
+ # Retros use the .retro.md extension.
8
+ module RetroFilePattern
9
+ # Glob pattern for retro files within a directory
10
+ FILE_GLOB = "*.retro.md"
11
+
12
+ # Full file extension for retro files
13
+ FILE_EXTENSION = ".retro.md"
14
+
15
+ # Build the retro filename
16
+ # @param id [String] Raw 6-char b36ts ID
17
+ # @param slug [String] Kebab-case slug
18
+ # @return [String] Retro filename (e.g., "8ppq7w-sprint-review.retro.md")
19
+ def self.retro_filename(id, slug)
20
+ "#{id}-#{slug}#{FILE_EXTENSION}"
21
+ end
22
+
23
+ # Build the folder name for a retro
24
+ # @param id [String] Raw 6-char b36ts ID
25
+ # @param slug [String] Kebab-case slug
26
+ # @return [String] Folder name (e.g., "8ppq7w-sprint-review")
27
+ def self.folder_name(id, slug)
28
+ "#{id}-#{slug}"
29
+ end
30
+
31
+ # Check if a filename matches the retro file pattern
32
+ # @param filename [String] Filename to check
33
+ # @return [Boolean] True if it's a retro file
34
+ def self.retro_file?(filename)
35
+ filename.to_s.end_with?(FILE_EXTENSION)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "time"
4
+
5
+ module Ace
6
+ module Retro
7
+ module Atoms
8
+ # Provides default frontmatter values for retro files.
9
+ # Generates the canonical YAML frontmatter block for new retros.
10
+ module RetroFrontmatterDefaults
11
+ # Build frontmatter hash for a new retro
12
+ # @param id [String] Raw 6-char b36ts ID
13
+ # @param title [String] Retro title
14
+ # @param type [String] Retro type (standard, conversation-analysis, self-review)
15
+ # @param tags [Array<String>] List of tags (default: [])
16
+ # @param status [String] Initial status (default: "active")
17
+ # @param created_at [Time] Creation time (default: now)
18
+ # @return [Hash] Frontmatter hash ready for YAML serialization
19
+ def self.build(id:, title:, type: "standard", tags: [], status: "active",
20
+ created_at: Time.now.utc)
21
+ {
22
+ "id" => id,
23
+ "title" => title,
24
+ "type" => type,
25
+ "tags" => Array(tags),
26
+ "created_at" => created_at.strftime("%Y-%m-%d %H:%M:%S"),
27
+ "status" => status
28
+ }
29
+ end
30
+
31
+ # Serialize frontmatter hash to YAML block string.
32
+ # Delegates to the shared FrontmatterSerializer atom.
33
+ # @param frontmatter [Hash] Frontmatter data
34
+ # @return [String] YAML frontmatter block including delimiters
35
+ def self.serialize(frontmatter)
36
+ require "ace/support/items"
37
+ Ace::Support::Items::Atoms::FrontmatterSerializer.serialize(frontmatter)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ace/b36ts"
4
+
5
+ module Ace
6
+ module Retro
7
+ module Atoms
8
+ # Generates and formats raw b36ts IDs for retros.
9
+ # Retros use raw 6-char b36ts IDs without type markers.
10
+ # Example: "8ppq7w" (no ".t." or ".i." separator)
11
+ class RetroIdFormatter
12
+ # Generate a new raw 6-char b36ts ID for a retro
13
+ # @param time [Time] Time to encode (default: now)
14
+ # @return [String] 6-character raw b36ts ID (e.g., "8ppq7w")
15
+ def self.generate(time = Time.now.utc)
16
+ Ace::B36ts.encode(time, format: :"2sec")
17
+ end
18
+
19
+ # Validate that a string is a valid raw retro ID
20
+ # @param id [String] The ID to validate
21
+ # @return [Boolean] True if valid 6-char b36ts ID
22
+ def self.valid?(id)
23
+ return false if id.nil? || id.empty?
24
+
25
+ Ace::B36ts.valid?(id)
26
+ end
27
+
28
+ # Decode a raw retro ID to the time it was created
29
+ # @param id [String] Raw 6-char b36ts ID
30
+ # @return [Time] The time encoded in the ID
31
+ def self.decode_time(id)
32
+ Ace::B36ts.decode(id)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "retro_id_formatter"
4
+
5
+ module Ace
6
+ module Retro
7
+ module Atoms
8
+ # Pure validation predicates and constants for retro health checking.
9
+ # Used by doctor validators to determine correctness of frontmatter,
10
+ # file structure, and scope/status consistency.
11
+ module RetroValidationRules
12
+ VALID_STATUSES = %w[active done].freeze
13
+ TERMINAL_STATUSES = %w[done].freeze
14
+ REQUIRED_FIELDS = %w[id title type status created_at].freeze
15
+ RECOMMENDED_FIELDS = %w[tags].freeze
16
+
17
+ # Check if a status string is valid
18
+ # @param status [String] Status to validate
19
+ # @return [Boolean]
20
+ def self.valid_status?(status)
21
+ VALID_STATUSES.include?(status.to_s)
22
+ end
23
+
24
+ # Check if a status is terminal (belongs in _archive)
25
+ # @param status [String] Status to check
26
+ # @return [Boolean]
27
+ def self.terminal_status?(status)
28
+ TERMINAL_STATUSES.include?(status.to_s)
29
+ end
30
+
31
+ # Check if an ID string is a valid b36ts retro ID
32
+ # @param id [String] ID to validate
33
+ # @return [Boolean]
34
+ def self.valid_id?(id)
35
+ RetroIdFormatter.valid?(id)
36
+ end
37
+
38
+ # Check if scope (special folder) is consistent with status
39
+ # @param status [String] Retro status
40
+ # @param special_folder [String, nil] Special folder name (e.g., "_archive", nil)
41
+ # @return [Array<Hash>] List of inconsistency issues (empty if consistent)
42
+ def self.scope_consistent?(status, special_folder)
43
+ issues = []
44
+
45
+ if terminal_status?(status) && special_folder != "_archive"
46
+ issues << {
47
+ type: :warning,
48
+ message: "Retro with terminal status '#{status}' not in _archive/"
49
+ }
50
+ end
51
+
52
+ if special_folder == "_archive" && !terminal_status?(status) && status
53
+ issues << {
54
+ type: :warning,
55
+ message: "Retro in _archive/ but status is '#{status}' (expected terminal status)"
56
+ }
57
+ end
58
+
59
+ issues
60
+ end
61
+
62
+ # Return list of missing required fields from frontmatter
63
+ # @param frontmatter [Hash] Parsed frontmatter
64
+ # @return [Array<String>] Names of missing required fields
65
+ def self.missing_required_fields(frontmatter)
66
+ return REQUIRED_FIELDS.dup if frontmatter.nil? || !frontmatter.is_a?(Hash)
67
+
68
+ REQUIRED_FIELDS.select { |field| frontmatter[field].nil? || frontmatter[field].to_s.strip.empty? }
69
+ end
70
+
71
+ # Return list of missing recommended fields from frontmatter
72
+ # @param frontmatter [Hash] Parsed frontmatter
73
+ # @return [Array<String>] Names of missing recommended fields
74
+ def self.missing_recommended_fields(frontmatter)
75
+ return RECOMMENDED_FIELDS.dup if frontmatter.nil? || !frontmatter.is_a?(Hash)
76
+
77
+ RECOMMENDED_FIELDS.select { |field| frontmatter[field].nil? }
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ace/support/cli"
4
+
5
+ module Ace
6
+ module Retro
7
+ module CLI
8
+ module Commands
9
+ # ace-support-cli Command class for ace-retro create
10
+ class Create < Ace::Support::Cli::Command
11
+ include Ace::Support::Cli::Base
12
+
13
+ desc <<~DESC.strip
14
+ Create a new retro
15
+
16
+ Creates a new retrospective with title, type, and tags.
17
+
18
+ DESC
19
+
20
+ example [
21
+ '"Sprint Review" --type standard --tags sprint,team # Standard retro',
22
+ '"Quick self-review" --type self-review # Self-review retro',
23
+ '"Sprint Review" --move-to archive # Create in _archive/',
24
+ '"Sprint Review" --dry-run # Preview without writing'
25
+ ]
26
+
27
+ argument :title, required: false, desc: "Retro title"
28
+
29
+ option :type, type: :string, aliases: %w[-t], desc: "Retro type (standard, conversation-analysis, self-review)"
30
+ option :tags, type: :string, aliases: %w[-T], desc: "Comma-separated tags"
31
+ option :"move-to", type: :string, aliases: %w[-m], desc: "Target folder (e.g. archive)"
32
+ option :"dry-run", type: :boolean, aliases: %w[-n], desc: "Preview without writing"
33
+
34
+ option :git_commit, type: :boolean, aliases: %w[--gc], desc: "Auto-commit changes"
35
+
36
+ option :quiet, type: :boolean, aliases: %w[-q], desc: "Suppress non-essential output"
37
+ option :verbose, type: :boolean, aliases: %w[-v], desc: "Show verbose output"
38
+ option :debug, type: :boolean, aliases: %w[-d], desc: "Show debug output"
39
+
40
+ def call(title: nil, **options)
41
+ type = options[:type]
42
+ tags_str = options[:tags]
43
+ move_to = options[:"move-to"]
44
+ dry_run = options[:"dry-run"]
45
+
46
+ tags = tags_str ? tags_str.split(",").map(&:strip).reject(&:empty?) : []
47
+
48
+ unless title
49
+ warn "Error: title is required"
50
+ warn ""
51
+ warn "Usage: ace-retro create TITLE [--type TYPE] [--tags T1,T2] [--move-to FOLDER]"
52
+ raise Ace::Support::Cli::Error.new("Title required")
53
+ end
54
+
55
+ if dry_run
56
+ puts "Would create retro:"
57
+ puts " Title: #{title}"
58
+ puts " Type: #{type || "standard"}"
59
+ puts " Tags: #{tags.any? ? tags.join(", ") : "(none)"}"
60
+ puts " Folder: #{move_to ? "_#{move_to.delete_prefix("_")}" : "(root)"}"
61
+ return
62
+ end
63
+
64
+ manager = Ace::Retro::Organisms::RetroManager.new
65
+ retro = manager.create(
66
+ title,
67
+ type: type,
68
+ tags: tags,
69
+ move_to: move_to
70
+ )
71
+
72
+ folder_info = retro.special_folder ? " (#{retro.special_folder})" : ""
73
+ puts "Retro created: #{retro.id} #{retro.title}#{folder_info}"
74
+ puts " Path: #{retro.file_path}"
75
+
76
+ if options[:git_commit]
77
+ Ace::Support::Items::Molecules::GitCommitter.commit(
78
+ paths: [retro.path],
79
+ intention: "create retro #{retro.id}"
80
+ )
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end