ace-handbook 0.19.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.
- checksums.yaml +7 -0
- data/.ace-defaults/handbook/config.yml +4 -0
- data/.ace-defaults/nav/protocols/guide-sources/ace-handbook.yml +19 -0
- data/.ace-defaults/nav/protocols/tmpl-sources/ace-handbook.yml +10 -0
- data/.ace-defaults/nav/protocols/wfi-sources/ace-handbook.yml +19 -0
- data/CHANGELOG.md +362 -0
- data/LICENSE +21 -0
- data/README.md +42 -0
- data/Rakefile +12 -0
- data/exe/ace-handbook +6 -0
- data/handbook/guides/ai-agent-integration.g.md +625 -0
- data/handbook/guides/atom-pattern.g.md +371 -0
- data/handbook/guides/changelog.g.md +333 -0
- data/handbook/guides/cli-dry-cli.g.md +276 -0
- data/handbook/guides/cli-support-cli.g.md +277 -0
- data/handbook/guides/coding-standards/ruby.md +41 -0
- data/handbook/guides/coding-standards/rust.md +19 -0
- data/handbook/guides/coding-standards/typescript.md +20 -0
- data/handbook/guides/coding-standards.g.md +134 -0
- data/handbook/guides/debug-troubleshooting.g.md +62 -0
- data/handbook/guides/error-handling/ruby.md +29 -0
- data/handbook/guides/error-handling/rust.md +59 -0
- data/handbook/guides/error-handling/typescript.md +38 -0
- data/handbook/guides/error-handling.g.md +207 -0
- data/handbook/guides/meta/agents-definition.g.md +823 -0
- data/handbook/guides/meta/guides-definition.g.md +322 -0
- data/handbook/guides/meta/markdown-definition.g.md +210 -0
- data/handbook/guides/meta/tools-definition.g.md +159 -0
- data/handbook/guides/meta/workflow-instructions-definition.g.md +367 -0
- data/handbook/guides/mono-repo-patterns.g.md +92 -0
- data/handbook/guides/multi-agent-research.g.md +251 -0
- data/handbook/guides/performance/ruby.md +25 -0
- data/handbook/guides/performance/rust.md +48 -0
- data/handbook/guides/performance/typescript.md +32 -0
- data/handbook/guides/performance.g.md +211 -0
- data/handbook/guides/prompt-caching.g.md +83 -0
- data/handbook/guides/quality-assurance/ruby.md +33 -0
- data/handbook/guides/quality-assurance/rust.md +41 -0
- data/handbook/guides/quality-assurance/typescript.md +49 -0
- data/handbook/guides/quality-assurance.g.md +222 -0
- data/handbook/guides/strategic-planning.g.md +69 -0
- data/handbook/guides/troubleshooting/ruby.md +21 -0
- data/handbook/guides/troubleshooting/rust.md +20 -0
- data/handbook/guides/troubleshooting/typescript.md +36 -0
- data/handbook/guides/workflow-context-embedding.g.md +286 -0
- data/handbook/skills/as-handbook-init-project/SKILL.md +34 -0
- data/handbook/skills/as-handbook-manage-agents/SKILL.md +35 -0
- data/handbook/skills/as-handbook-manage-guides/SKILL.md +35 -0
- data/handbook/skills/as-handbook-manage-workflows/SKILL.md +35 -0
- data/handbook/skills/as-handbook-parallel-research/SKILL.md +29 -0
- data/handbook/skills/as-handbook-perform-delivery/SKILL.md +35 -0
- data/handbook/skills/as-handbook-review-guides/SKILL.md +32 -0
- data/handbook/skills/as-handbook-review-workflows/SKILL.md +32 -0
- data/handbook/skills/as-handbook-synthesize-research/SKILL.md +29 -0
- data/handbook/skills/as-handbook-update-docs/SKILL.md +35 -0
- data/handbook/skills/as-release/SKILL.md +50 -0
- data/handbook/skills/as-release-bump-version/SKILL.md +28 -0
- data/handbook/skills/as-release-rubygems-publish/SKILL.md +58 -0
- data/handbook/skills/as-release-update-changelog/SKILL.md +28 -0
- data/handbook/templates/completed-work-documentation.md +59 -0
- data/handbook/templates/cookbooks/cookbook.template.md +237 -0
- data/handbook/templates/research-comparison.template.md +175 -0
- data/handbook/workflow-instructions/handbook/init-project.wf.md +629 -0
- data/handbook/workflow-instructions/handbook/manage-agents.wf.md +379 -0
- data/handbook/workflow-instructions/handbook/manage-guides.wf.md +294 -0
- data/handbook/workflow-instructions/handbook/manage-workflows.wf.md +292 -0
- data/handbook/workflow-instructions/handbook/parallel-research.wf.md +328 -0
- data/handbook/workflow-instructions/handbook/perform-delivery.wf.md +267 -0
- data/handbook/workflow-instructions/handbook/research.wf.md +247 -0
- data/handbook/workflow-instructions/handbook/review-guides.wf.md +348 -0
- data/handbook/workflow-instructions/handbook/review-workflows.wf.md +299 -0
- data/handbook/workflow-instructions/handbook/synthesize-research.wf.md +429 -0
- data/handbook/workflow-instructions/handbook/update-docs.wf.md +338 -0
- data/lib/ace/handbook/atoms/provider_registry.rb +70 -0
- data/lib/ace/handbook/cli/commands/status.rb +36 -0
- data/lib/ace/handbook/cli/commands/sync.rb +36 -0
- data/lib/ace/handbook/cli.rb +51 -0
- data/lib/ace/handbook/models/skill_document.rb +25 -0
- data/lib/ace/handbook/molecules/skill_projection.rb +54 -0
- data/lib/ace/handbook/organisms/provider_syncer.rb +106 -0
- data/lib/ace/handbook/organisms/skill_inventory.rb +54 -0
- data/lib/ace/handbook/organisms/status_collector.rb +181 -0
- data/lib/ace/handbook/version.rb +7 -0
- data/lib/ace/handbook.rb +28 -0
- metadata +227 -0
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
---
|
|
2
|
+
doc-type: guide
|
|
3
|
+
title: dry-cli CLI Framework Guide
|
|
4
|
+
purpose: Documentation for ace-handbook/handbook/guides/cli-dry-cli.g.md
|
|
5
|
+
ace-docs:
|
|
6
|
+
last-updated: 2026-02-22
|
|
7
|
+
last-checked: 2026-03-21
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# dry-cli CLI Framework Guide
|
|
11
|
+
|
|
12
|
+
Complete reference for implementing CLI interfaces in ace-* gems using dry-cli.
|
|
13
|
+
|
|
14
|
+
## Overview
|
|
15
|
+
|
|
16
|
+
All ACE CLI gems use dry-cli. See [ADR-023](../../../docs/decisions/ADR-023-dry-cli-framework.md) for decision rationale.
|
|
17
|
+
|
|
18
|
+
**Two patterns:**
|
|
19
|
+
- **Multi-command**: Subcommand tools (ace-bundle, ace-taskflow)
|
|
20
|
+
- **Single-command**: One-action tools (ace-git-commit, ace-search)
|
|
21
|
+
|
|
22
|
+
## Multi-Command Pattern
|
|
23
|
+
|
|
24
|
+
For CLIs with subcommands, use the Registry pattern with `HelpCommand.build()`:
|
|
25
|
+
|
|
26
|
+
```ruby
|
|
27
|
+
# lib/ace/gem/cli.rb
|
|
28
|
+
require "dry/cli"
|
|
29
|
+
require "ace/core"
|
|
30
|
+
require_relative "cli/commands/process"
|
|
31
|
+
require_relative "cli/commands/status"
|
|
32
|
+
|
|
33
|
+
module Ace::Gem
|
|
34
|
+
module CLI
|
|
35
|
+
extend Dry::CLI::Registry
|
|
36
|
+
|
|
37
|
+
PROGRAM_NAME = 'ace-gem'
|
|
38
|
+
|
|
39
|
+
# Commands with descriptions for help output
|
|
40
|
+
REGISTERED_COMMANDS = [
|
|
41
|
+
['process', 'Process files with auto-detection'],
|
|
42
|
+
['status', 'Show current status']
|
|
43
|
+
].freeze
|
|
44
|
+
|
|
45
|
+
HELP_EXAMPLES = [
|
|
46
|
+
'ace-gem process file.txt',
|
|
47
|
+
'ace-gem status --verbose'
|
|
48
|
+
].freeze
|
|
49
|
+
|
|
50
|
+
register 'process', Commands::Process.new
|
|
51
|
+
register 'status', Commands::Status.new
|
|
52
|
+
|
|
53
|
+
# Version command
|
|
54
|
+
version_cmd = Ace::Core::CLI::DryCli::VersionCommand.build(
|
|
55
|
+
gem_name: 'ace-gem',
|
|
56
|
+
version: Ace::Gem::VERSION
|
|
57
|
+
)
|
|
58
|
+
register 'version', version_cmd
|
|
59
|
+
register '--version', version_cmd
|
|
60
|
+
|
|
61
|
+
# Help command (standard pattern)
|
|
62
|
+
help_cmd = Ace::Core::CLI::DryCli::HelpCommand.build(
|
|
63
|
+
program_name: PROGRAM_NAME,
|
|
64
|
+
version: Ace::Gem::VERSION,
|
|
65
|
+
commands: REGISTERED_COMMANDS,
|
|
66
|
+
examples: HELP_EXAMPLES
|
|
67
|
+
)
|
|
68
|
+
register 'help', help_cmd
|
|
69
|
+
register '--help', help_cmd
|
|
70
|
+
register '-h', help_cmd
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**Exe wrapper:**
|
|
76
|
+
```ruby
|
|
77
|
+
#!/usr/bin/env ruby
|
|
78
|
+
require "ace/gem"
|
|
79
|
+
|
|
80
|
+
args = ARGV.empty? ? ["--help"] : ARGV
|
|
81
|
+
|
|
82
|
+
begin
|
|
83
|
+
Dry::CLI.new(Ace::Gem::CLI).call(arguments: args)
|
|
84
|
+
rescue Ace::Core::CLI::Error => e
|
|
85
|
+
warn e.message
|
|
86
|
+
exit(e.exit_code)
|
|
87
|
+
end
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Single-Command Pattern
|
|
91
|
+
|
|
92
|
+
For CLIs with one primary action, skip the registry:
|
|
93
|
+
|
|
94
|
+
```ruby
|
|
95
|
+
# lib/ace/gem/cli/commands/search.rb
|
|
96
|
+
module Ace::Gem
|
|
97
|
+
module CLI
|
|
98
|
+
module Commands
|
|
99
|
+
class Search < Dry::CLI::Command
|
|
100
|
+
include Ace::Core::CLI::DryCli::Base
|
|
101
|
+
|
|
102
|
+
desc "Search files and content"
|
|
103
|
+
argument :pattern, required: false
|
|
104
|
+
option :files, type: :boolean, aliases: ["-f"]
|
|
105
|
+
|
|
106
|
+
def call(pattern: nil, **options)
|
|
107
|
+
# ... implementation
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
**Exe wrapper:**
|
|
116
|
+
```ruby
|
|
117
|
+
#!/usr/bin/env ruby
|
|
118
|
+
require "ace/gem"
|
|
119
|
+
|
|
120
|
+
args = ARGV.empty? ? ["--help"] : ARGV
|
|
121
|
+
|
|
122
|
+
begin
|
|
123
|
+
Dry::CLI.new(Ace::Gem::CLI::Commands::Search).call(arguments: args)
|
|
124
|
+
rescue Ace::Core::CLI::Error => e
|
|
125
|
+
warn e.message
|
|
126
|
+
exit(e.exit_code)
|
|
127
|
+
end
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Command Class Pattern
|
|
131
|
+
|
|
132
|
+
Commands use `CLI::Commands::` namespace (Hanami pattern):
|
|
133
|
+
|
|
134
|
+
```ruby
|
|
135
|
+
# lib/ace/gem/cli/commands/process.rb
|
|
136
|
+
module Ace::Gem
|
|
137
|
+
module CLI
|
|
138
|
+
module Commands
|
|
139
|
+
class Process < Dry::CLI::Command
|
|
140
|
+
include Ace::Core::CLI::DryCli::Base
|
|
141
|
+
|
|
142
|
+
desc "Process file with auto-detection"
|
|
143
|
+
|
|
144
|
+
argument :file, required: false, desc: "File to process"
|
|
145
|
+
option :quiet, type: :boolean, aliases: %w[-q], desc: "Suppress output"
|
|
146
|
+
option :verbose, type: :boolean, aliases: %w[-v], desc: "Verbose output"
|
|
147
|
+
option :debug, type: :boolean, aliases: %w[-d], desc: "Debug output"
|
|
148
|
+
|
|
149
|
+
def call(file: nil, **options)
|
|
150
|
+
ProcessCommand.new(file, options).execute
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
**Directory structure**: `lib/ace/gem/cli/commands/` (not `lib/ace/gem/commands/`)
|
|
159
|
+
|
|
160
|
+
## Nested Commands
|
|
161
|
+
|
|
162
|
+
For hierarchical commands (ace-taskflow, ace-git-worktree):
|
|
163
|
+
|
|
164
|
+
```ruby
|
|
165
|
+
# lib/ace/taskflow/cli.rb
|
|
166
|
+
module Ace::Taskflow
|
|
167
|
+
module CLI
|
|
168
|
+
extend Dry::CLI::Registry
|
|
169
|
+
|
|
170
|
+
# Hierarchical registration with space-separated names
|
|
171
|
+
register "task show", Commands::Task::Show
|
|
172
|
+
register "task list", Commands::Task::List
|
|
173
|
+
register "release bump", Commands::Release::Bump
|
|
174
|
+
|
|
175
|
+
# Help and version
|
|
176
|
+
help_cmd = Ace::Core::CLI::DryCli::HelpCommand.build(...)
|
|
177
|
+
register "help", help_cmd
|
|
178
|
+
register "--help", help_cmd
|
|
179
|
+
register "-h", help_cmd
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# Directory structure:
|
|
184
|
+
# lib/ace/taskflow/cli/commands/task/show.rb
|
|
185
|
+
# lib/ace/taskflow/cli/commands/task/list.rb
|
|
186
|
+
# lib/ace/taskflow/cli/commands/release/bump.rb
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Type Conversion
|
|
190
|
+
|
|
191
|
+
dry-cli returns strings for all options. Use the `convert_types` helper:
|
|
192
|
+
|
|
193
|
+
```ruby
|
|
194
|
+
# Single option
|
|
195
|
+
opts = convert_types(options, timeout: :integer)
|
|
196
|
+
|
|
197
|
+
# Multiple options
|
|
198
|
+
opts = convert_types(options, limit: :integer, ratio: :float)
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Help Documentation
|
|
202
|
+
|
|
203
|
+
Use `desc` with heredoc and `example` array:
|
|
204
|
+
|
|
205
|
+
```ruby
|
|
206
|
+
desc <<~DESC.strip
|
|
207
|
+
Main description here.
|
|
208
|
+
|
|
209
|
+
Additional context:
|
|
210
|
+
- Point one
|
|
211
|
+
- Point two
|
|
212
|
+
DESC
|
|
213
|
+
|
|
214
|
+
example ['pattern --flag', '"*.rb" -f']
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Exit Code Handling
|
|
218
|
+
|
|
219
|
+
**IMPORTANT**: dry-cli's `call()` method returns `nil`, NOT command return values. Use exception-based exit codes:
|
|
220
|
+
|
|
221
|
+
```ruby
|
|
222
|
+
# In command - raise exception for non-zero exit
|
|
223
|
+
def call(file: nil, **options)
|
|
224
|
+
raise Ace::Core::CLI::Error.new("file required") if file.nil?
|
|
225
|
+
|
|
226
|
+
result = do_work(file)
|
|
227
|
+
raise Ace::Core::CLI::Error.new(result[:error]) unless result[:success]
|
|
228
|
+
|
|
229
|
+
puts result[:message]
|
|
230
|
+
# Success - no exception, exits 0
|
|
231
|
+
end
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
**Exe wrapper catches exceptions:**
|
|
235
|
+
```ruby
|
|
236
|
+
#!/usr/bin/env ruby
|
|
237
|
+
require "ace/gem"
|
|
238
|
+
|
|
239
|
+
args = ARGV.empty? ? ["--help"] : ARGV
|
|
240
|
+
|
|
241
|
+
begin
|
|
242
|
+
Dry::CLI.new(Ace::Gem::CLI).call(arguments: args)
|
|
243
|
+
rescue Ace::Core::CLI::Error => e
|
|
244
|
+
warn e.message
|
|
245
|
+
exit(e.exit_code)
|
|
246
|
+
rescue Interrupt
|
|
247
|
+
warn "\nInterrupted"
|
|
248
|
+
exit(130)
|
|
249
|
+
end
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
**Exit Code Values:**
|
|
253
|
+
| Code | Meaning |
|
|
254
|
+
|------|---------|
|
|
255
|
+
| 0 | Success |
|
|
256
|
+
| 1 | General failure |
|
|
257
|
+
| 2 | Invalid arguments |
|
|
258
|
+
| 130 | SIGINT (Ctrl+C) |
|
|
259
|
+
|
|
260
|
+
See [ADR-023](../../../docs/decisions/ADR-023-dry-cli-framework.md) for full exit code documentation.
|
|
261
|
+
|
|
262
|
+
## Reserved Short Flags
|
|
263
|
+
|
|
264
|
+
| Flag | Meaning | Notes |
|
|
265
|
+
|------|---------|-------|
|
|
266
|
+
| `-h` | help | dry-cli default |
|
|
267
|
+
| `-v` | verbose | NOT version |
|
|
268
|
+
| `-q` | quiet | Suppress output |
|
|
269
|
+
| `-d` | debug | Debug output |
|
|
270
|
+
| `-o` | output | Output destination |
|
|
271
|
+
|
|
272
|
+
## Related
|
|
273
|
+
|
|
274
|
+
- [ADR-023](../../../docs/decisions/ADR-023-dry-cli-framework.md) - Decision record
|
|
275
|
+
- [ace-gems.g.md](../../../docs/ace-gems.g.md) - Gem development overview
|
|
276
|
+
- Task 179 - Migration details
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
---
|
|
2
|
+
doc-type: guide
|
|
3
|
+
title: ace-support-cli CLI Framework Guide
|
|
4
|
+
purpose: Documentation for ace-handbook/handbook/guides/cli-support-cli.g.md
|
|
5
|
+
ace-docs:
|
|
6
|
+
last-updated: 2026-03-18
|
|
7
|
+
last-checked: 2026-03-21
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# ace-support-cli CLI Framework Guide
|
|
11
|
+
|
|
12
|
+
Complete reference for implementing CLI interfaces in ace-* gems using ace-support-cli.
|
|
13
|
+
|
|
14
|
+
## Overview
|
|
15
|
+
|
|
16
|
+
All ACE CLI gems use ace-support-cli. See [ADR-023](../../../docs/decisions/ADR-023-ace-support-cli-framework.md) for decision rationale.
|
|
17
|
+
|
|
18
|
+
**Two patterns:**
|
|
19
|
+
- **Multi-command**: Subcommand tools (ace-bundle, ace-taskflow)
|
|
20
|
+
- **Single-command**: One-action tools (ace-git-commit, ace-search)
|
|
21
|
+
|
|
22
|
+
## Multi-Command Pattern
|
|
23
|
+
|
|
24
|
+
For CLIs with subcommands, use the Registry pattern with `HelpCommand.build()`:
|
|
25
|
+
|
|
26
|
+
```ruby
|
|
27
|
+
# lib/ace/gem/cli.rb
|
|
28
|
+
require "ace/support/cli"
|
|
29
|
+
require "ace/core"
|
|
30
|
+
require_relative "cli/commands/process"
|
|
31
|
+
require_relative "cli/commands/status"
|
|
32
|
+
|
|
33
|
+
module Ace::Gem
|
|
34
|
+
module CLI
|
|
35
|
+
extend Ace::Core::CLI::RegistryDsl
|
|
36
|
+
|
|
37
|
+
PROGRAM_NAME = 'ace-gem'
|
|
38
|
+
|
|
39
|
+
# Commands with descriptions for help output
|
|
40
|
+
REGISTERED_COMMANDS = [
|
|
41
|
+
['process', 'Process files with auto-detection'],
|
|
42
|
+
['status', 'Show current status']
|
|
43
|
+
].freeze
|
|
44
|
+
|
|
45
|
+
HELP_EXAMPLES = [
|
|
46
|
+
'ace-gem process file.txt',
|
|
47
|
+
'ace-gem status --verbose'
|
|
48
|
+
].freeze
|
|
49
|
+
|
|
50
|
+
register 'process', Commands::Process
|
|
51
|
+
register 'status', Commands::Status
|
|
52
|
+
|
|
53
|
+
# Version command
|
|
54
|
+
version_cmd = Ace::Core::CLI::VersionCommand.build(
|
|
55
|
+
gem_name: 'ace-gem',
|
|
56
|
+
version: Ace::Gem::VERSION
|
|
57
|
+
)
|
|
58
|
+
register 'version', version_cmd
|
|
59
|
+
register '--version', version_cmd
|
|
60
|
+
|
|
61
|
+
# Help command (standard pattern)
|
|
62
|
+
help_cmd = Ace::Core::CLI::HelpCommand.build(
|
|
63
|
+
program_name: PROGRAM_NAME,
|
|
64
|
+
version: Ace::Gem::VERSION,
|
|
65
|
+
commands: REGISTERED_COMMANDS,
|
|
66
|
+
examples: HELP_EXAMPLES
|
|
67
|
+
)
|
|
68
|
+
register 'help', help_cmd
|
|
69
|
+
register '--help', help_cmd
|
|
70
|
+
register '-h', help_cmd
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**Exe wrapper:**
|
|
76
|
+
```ruby
|
|
77
|
+
#!/usr/bin/env ruby
|
|
78
|
+
require "ace/gem"
|
|
79
|
+
|
|
80
|
+
args = ARGV.empty? ? ["--help"] : ARGV
|
|
81
|
+
|
|
82
|
+
begin
|
|
83
|
+
Ace::Support::Cli::Runner.new(Ace::Gem::CLI).call(args: args)
|
|
84
|
+
rescue Ace::Core::CLI::Error => e
|
|
85
|
+
warn e.message
|
|
86
|
+
exit(e.exit_code)
|
|
87
|
+
end
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Single-Command Pattern
|
|
91
|
+
|
|
92
|
+
For CLIs with one primary action, skip the registry:
|
|
93
|
+
|
|
94
|
+
```ruby
|
|
95
|
+
# lib/ace/gem/cli/commands/search.rb
|
|
96
|
+
module Ace::Gem
|
|
97
|
+
module CLI
|
|
98
|
+
module Commands
|
|
99
|
+
class Search < Ace::Support::Cli::Command
|
|
100
|
+
include Ace::Core::CLI::Base
|
|
101
|
+
|
|
102
|
+
desc "Search files and content"
|
|
103
|
+
argument :pattern, required: false
|
|
104
|
+
option :files, type: :boolean, aliases: ["-f"]
|
|
105
|
+
|
|
106
|
+
def call(pattern: nil, **options)
|
|
107
|
+
# ... implementation
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
**Exe wrapper:**
|
|
116
|
+
```ruby
|
|
117
|
+
#!/usr/bin/env ruby
|
|
118
|
+
require "ace/gem"
|
|
119
|
+
|
|
120
|
+
args = ARGV.empty? ? ["--help"] : ARGV
|
|
121
|
+
|
|
122
|
+
begin
|
|
123
|
+
Ace::Support::Cli::Runner.new(Ace::Gem::CLI::Commands::Search).call(args: args)
|
|
124
|
+
rescue Ace::Core::CLI::Error => e
|
|
125
|
+
warn e.message
|
|
126
|
+
exit(e.exit_code)
|
|
127
|
+
end
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Command Class Pattern
|
|
131
|
+
|
|
132
|
+
Commands use `CLI::Commands::` namespace (Hanami pattern):
|
|
133
|
+
|
|
134
|
+
```ruby
|
|
135
|
+
# lib/ace/gem/cli/commands/process.rb
|
|
136
|
+
module Ace::Gem
|
|
137
|
+
module CLI
|
|
138
|
+
module Commands
|
|
139
|
+
class Process < Ace::Support::Cli::Command
|
|
140
|
+
include Ace::Core::CLI::Base
|
|
141
|
+
|
|
142
|
+
desc "Process file with auto-detection"
|
|
143
|
+
|
|
144
|
+
argument :file, required: false, desc: "File to process"
|
|
145
|
+
option :quiet, type: :boolean, aliases: %w[-q], desc: "Suppress output"
|
|
146
|
+
option :verbose, type: :boolean, aliases: %w[-v], desc: "Verbose output"
|
|
147
|
+
option :debug, type: :boolean, aliases: %w[-d], desc: "Debug output"
|
|
148
|
+
|
|
149
|
+
def call(file: nil, **options)
|
|
150
|
+
ProcessCommand.new(file, options).execute
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
**Directory structure**: `lib/ace/gem/cli/commands/` (not `lib/ace/gem/commands/`)
|
|
159
|
+
|
|
160
|
+
## Nested Commands
|
|
161
|
+
|
|
162
|
+
For hierarchical commands (ace-taskflow, ace-git-worktree):
|
|
163
|
+
|
|
164
|
+
```ruby
|
|
165
|
+
# lib/ace/taskflow/cli.rb
|
|
166
|
+
module Ace::Taskflow
|
|
167
|
+
module CLI
|
|
168
|
+
extend Ace::Core::CLI::RegistryDsl
|
|
169
|
+
|
|
170
|
+
# Hierarchical registration with space-separated names
|
|
171
|
+
register "task show", Commands::Task::Show
|
|
172
|
+
register "task list", Commands::Task::List
|
|
173
|
+
register "release bump", Commands::Release::Bump
|
|
174
|
+
|
|
175
|
+
# Help and version
|
|
176
|
+
help_cmd = Ace::Core::CLI::HelpCommand.build(...)
|
|
177
|
+
register "help", help_cmd
|
|
178
|
+
register "--help", help_cmd
|
|
179
|
+
register "-h", help_cmd
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# Directory structure:
|
|
184
|
+
# lib/ace/taskflow/cli/commands/task/show.rb
|
|
185
|
+
# lib/ace/taskflow/cli/commands/task/list.rb
|
|
186
|
+
# lib/ace/taskflow/cli/commands/release/bump.rb
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Type Conversion
|
|
190
|
+
|
|
191
|
+
Use the `coerce_types` helper from `Ace::Core::CLI::Base` when you need to coerce values manually:
|
|
192
|
+
|
|
193
|
+
```ruby
|
|
194
|
+
# Single option
|
|
195
|
+
opts = coerce_types(options, timeout: :integer)
|
|
196
|
+
|
|
197
|
+
# Multiple options
|
|
198
|
+
opts = coerce_types(options, limit: :integer, ratio: :float)
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Help Documentation
|
|
202
|
+
|
|
203
|
+
Use `desc` with heredoc and `example` array:
|
|
204
|
+
|
|
205
|
+
```ruby
|
|
206
|
+
desc <<~DESC.strip
|
|
207
|
+
Main description here.
|
|
208
|
+
|
|
209
|
+
Additional context:
|
|
210
|
+
- Point one
|
|
211
|
+
- Point two
|
|
212
|
+
DESC
|
|
213
|
+
|
|
214
|
+
example ['pattern --flag', '"*.rb" -f']
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Exit Code Handling
|
|
218
|
+
|
|
219
|
+
**IMPORTANT**: `Ace::Support::Cli::Runner#call()` returns the command result, but normalizes `nil` to exit code `0`. Use exception-based exit codes for failures:
|
|
220
|
+
|
|
221
|
+
```ruby
|
|
222
|
+
# In command - raise exception for non-zero exit
|
|
223
|
+
def call(file: nil, **options)
|
|
224
|
+
raise Ace::Core::CLI::Error.new("file required") if file.nil?
|
|
225
|
+
|
|
226
|
+
result = do_work(file)
|
|
227
|
+
raise Ace::Core::CLI::Error.new(result[:error]) unless result[:success]
|
|
228
|
+
|
|
229
|
+
puts result[:message]
|
|
230
|
+
# Success - no exception, exits 0
|
|
231
|
+
end
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
**Exe wrapper catches exceptions:**
|
|
235
|
+
```ruby
|
|
236
|
+
#!/usr/bin/env ruby
|
|
237
|
+
require "ace/gem"
|
|
238
|
+
|
|
239
|
+
args = ARGV.empty? ? ["--help"] : ARGV
|
|
240
|
+
|
|
241
|
+
begin
|
|
242
|
+
exit_code = Ace::Support::Cli::Runner.new(Ace::Gem::CLI).call(args: args)
|
|
243
|
+
exit(exit_code) if exit_code.is_a?(Integer) && exit_code != 0
|
|
244
|
+
rescue Ace::Core::CLI::Error => e
|
|
245
|
+
warn e.message
|
|
246
|
+
exit(e.exit_code)
|
|
247
|
+
rescue Interrupt
|
|
248
|
+
warn "\nInterrupted"
|
|
249
|
+
exit(130)
|
|
250
|
+
end
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
**Exit Code Values:**
|
|
254
|
+
| Code | Meaning |
|
|
255
|
+
|------|---------|
|
|
256
|
+
| 0 | Success |
|
|
257
|
+
| 1 | General failure |
|
|
258
|
+
| 2 | Invalid arguments |
|
|
259
|
+
| 130 | SIGINT (Ctrl+C) |
|
|
260
|
+
|
|
261
|
+
See [ADR-023](../../../docs/decisions/ADR-023-ace-support-cli-framework.md) for full exit code documentation.
|
|
262
|
+
|
|
263
|
+
## Reserved Short Flags
|
|
264
|
+
|
|
265
|
+
| Flag | Meaning | Notes |
|
|
266
|
+
|------|---------|-------|
|
|
267
|
+
| `-h` | help | ace-support-cli default |
|
|
268
|
+
| `-v` | verbose | NOT version |
|
|
269
|
+
| `-q` | quiet | Suppress output |
|
|
270
|
+
| `-d` | debug | Debug output |
|
|
271
|
+
| `-o` | output | Output destination |
|
|
272
|
+
|
|
273
|
+
## Related
|
|
274
|
+
|
|
275
|
+
- [ADR-023](../../../docs/decisions/ADR-023-ace-support-cli-framework.md) - Decision record
|
|
276
|
+
- [ace-gems.g.md](../../../docs/ace-gems.g.md) - Gem development overview
|
|
277
|
+
- Task 179 - Migration details
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Ruby Coding Standards
|
|
2
|
+
|
|
3
|
+
This sub-guide captures conventions and idioms specific to Ruby development in this project. Follow these in
|
|
4
|
+
addition to the generic standards in `../coding-standards.md`.
|
|
5
|
+
|
|
6
|
+
## Idioms & Best Practices
|
|
7
|
+
|
|
8
|
+
- Follow the community Ruby Style Guide (<https://rubystyle.guide/>) unless overridden here.
|
|
9
|
+
- Prefer blocks and `yield` for configurability and iteration when appropriate.
|
|
10
|
+
- Use metaprogramming judiciously; prioritize clarity over cleverness.
|
|
11
|
+
- Leverage standard library features instead of reinventing the wheel.
|
|
12
|
+
|
|
13
|
+
## Formatting
|
|
14
|
+
|
|
15
|
+
- Indentation: 2 spaces (no tabs).
|
|
16
|
+
- Line length: 100 characters max.
|
|
17
|
+
- Use `standardrb` or `rubocop -A` to auto-correct formatting issues.
|
|
18
|
+
|
|
19
|
+
## Error Handling
|
|
20
|
+
|
|
21
|
+
- Derive custom errors from `Aira::Error` base class.
|
|
22
|
+
- Include contextual data (e.g., `user_id`, `task_id`) when raising.
|
|
23
|
+
|
|
24
|
+
## Testing Conventions
|
|
25
|
+
|
|
26
|
+
- Use RSpec with the directory layout defined in `guide://testing` (Ruby/RSpec section).
|
|
27
|
+
- Tag specs (`:unit`, `:integration`, `:e2e`) per the testing guide.
|
|
28
|
+
|
|
29
|
+
## File Organization
|
|
30
|
+
|
|
31
|
+
- Mirror production code structure under `spec/`.
|
|
32
|
+
- Group concerns into modules; avoid deep inheritance trees.
|
|
33
|
+
|
|
34
|
+
## Performance Tips
|
|
35
|
+
|
|
36
|
+
- Prefer `each` over `map` when you don’t need the new array.
|
|
37
|
+
- Avoid creating unnecessary objects in hot code paths.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
Refer back to the main coding standards guide for cross-language principles.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Rust Coding Standards
|
|
2
|
+
|
|
3
|
+
> This page is a language-specific companion to [../coding-standards.g.md](../coding-standards.g.md)
|
|
4
|
+
|
|
5
|
+
## Formatting & Style
|
|
6
|
+
|
|
7
|
+
- (Add Rust-specific formatting rules, e.g., `rustfmt` usage)
|
|
8
|
+
|
|
9
|
+
## Naming Conventions
|
|
10
|
+
|
|
11
|
+
- (Add Rust-specific naming conventions following Rust API guidelines)
|
|
12
|
+
|
|
13
|
+
## Best Practices
|
|
14
|
+
|
|
15
|
+
- (Add Rust-specific best practices, e.g., ownership, lifetimes, error handling with `Result`)
|
|
16
|
+
|
|
17
|
+
## Tooling
|
|
18
|
+
|
|
19
|
+
- (Mention relevant Rust linters like `clippy`, formatters like `rustfmt`)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
|
|
2
|
+
# TypeScript Coding Standards
|
|
3
|
+
|
|
4
|
+
> This page is a language-specific companion to [../coding-standards.g.md](../coding-standards.g.md)
|
|
5
|
+
|
|
6
|
+
## Formatting & Style
|
|
7
|
+
|
|
8
|
+
- (Add TypeScript-specific formatting rules, e.g., Prettier config, ESLint rules)
|
|
9
|
+
|
|
10
|
+
## Naming Conventions
|
|
11
|
+
|
|
12
|
+
- (Add TypeScript-specific naming conventions for variables, functions, classes, etc.)
|
|
13
|
+
|
|
14
|
+
## Best Practices
|
|
15
|
+
|
|
16
|
+
- (Add TypeScript-specific best practices, e.g., type safety, module usage)
|
|
17
|
+
|
|
18
|
+
## Tooling
|
|
19
|
+
|
|
20
|
+
- (Mention relevant TypeScript linters, formatters, etc.)
|