schwarm-cli 0.1.5 → 0.1.6
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 +4 -4
- data/lib/schwarm_cli/commands/base.rb +7 -0
- data/lib/schwarm_cli/commands/tasks.rb +11 -5
- data/lib/schwarm_cli/hands_off_task.rb +21 -8
- data/lib/schwarm_cli/template_resolver.rb +43 -0
- data/lib/schwarm_cli/version.rb +1 -1
- data/lib/schwarm_cli.rb +1 -0
- data/schwarm-skill.md +39 -2
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cb4e9030ccc6a70a2d35c94e5c2db414bae4b56550ae21128b2e3f612b56b6cf
|
|
4
|
+
data.tar.gz: 4c4bfd79d9b120f01764b4b482200757a5a3f4d1a1e8dba5c344486befebf48d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 326c318ea026081fb23c05cd552e5a78204af6f35dc96e2ff7d5da6c838d0b48646534ab914cc1bc6afa250844e6a6d2ab3895cf2da37fee44f671308c10fbc4
|
|
7
|
+
data.tar.gz: c15ba6b8d00b97e44e8b0642ab88753423043cbb4eafad9593fc8fdba0a22bc3a67168576fe76f5165386316bfe14e505411471d08dca4eb6e474ddea25a9d97
|
|
@@ -32,6 +32,13 @@ module SchwarmCli
|
|
|
32
32
|
abort "Error: #{e.message}"
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
+
# Resolves --template input (ID or exact name) to a schwarm template ID.
|
|
36
|
+
def resolve_template(ref)
|
|
37
|
+
SchwarmCli::TemplateResolver.new(client: client).resolve(ref)
|
|
38
|
+
rescue SchwarmCli::TemplateResolver::ResolutionError => e
|
|
39
|
+
abort "Error: #{e.message}"
|
|
40
|
+
end
|
|
41
|
+
|
|
35
42
|
def output_list(data, columns:)
|
|
36
43
|
if options[:json]
|
|
37
44
|
Formatters::Json.format(data)
|
|
@@ -34,7 +34,7 @@ module SchwarmCli
|
|
|
34
34
|
option :prompt, type: :string, desc: "Task prompt"
|
|
35
35
|
option :repo, type: :string, desc: "Repository ID, owner/repo, or GitHub URL"
|
|
36
36
|
option :status, type: :string, desc: "Initial status (draft/waiting)"
|
|
37
|
-
option :template, type: :string, desc: "Template ID"
|
|
37
|
+
option :template, type: :string, desc: "Template ID or name"
|
|
38
38
|
option :depends_on, type: :array, desc: "Dependency task IDs"
|
|
39
39
|
def create
|
|
40
40
|
handle_errors do
|
|
@@ -116,14 +116,13 @@ module SchwarmCli
|
|
|
116
116
|
option :prompt, type: :string, desc: "Task prompt"
|
|
117
117
|
option :repo, type: :string, desc: "Repository ID, owner/repo, or GitHub URL (skips origin auto-detect)"
|
|
118
118
|
option :name, type: :string, desc: "Task name (defaults to the branch name)"
|
|
119
|
+
option :template, type: :string, desc: "Task template ID or name"
|
|
119
120
|
def handoff
|
|
120
121
|
prompt = options[:prompt]
|
|
121
122
|
abort "Error: --prompt is required." if prompt.nil? || prompt.strip.empty?
|
|
122
123
|
|
|
123
124
|
handle_errors do
|
|
124
|
-
result = SchwarmCli::HandsOffTask.new(client: client).call(
|
|
125
|
-
prompt: prompt, repo_override: resolve_repo(options[:repo]), name_override: options[:name]
|
|
126
|
-
)
|
|
125
|
+
result = SchwarmCli::HandsOffTask.new(client: client).call(**handoff_attrs(prompt))
|
|
127
126
|
print_handoff_result(result)
|
|
128
127
|
end
|
|
129
128
|
end
|
|
@@ -148,11 +147,18 @@ module SchwarmCli
|
|
|
148
147
|
end
|
|
149
148
|
end
|
|
150
149
|
|
|
150
|
+
def handoff_attrs(prompt)
|
|
151
|
+
{
|
|
152
|
+
prompt: prompt, repo_override: resolve_repo(options[:repo]),
|
|
153
|
+
name_override: options[:name], template_override: options[:template]
|
|
154
|
+
}
|
|
155
|
+
end
|
|
156
|
+
|
|
151
157
|
def create_attrs
|
|
152
158
|
{
|
|
153
159
|
name: options[:name], prompt: options[:prompt],
|
|
154
160
|
github_repository_id: resolve_repo(options[:repo]), status: options[:status],
|
|
155
|
-
task_template_id: options[:template], dependency_ids: options[:depends_on]
|
|
161
|
+
task_template_id: resolve_template(options[:template]), dependency_ids: options[:depends_on]
|
|
156
162
|
}.compact
|
|
157
163
|
end
|
|
158
164
|
|
|
@@ -12,14 +12,18 @@ module SchwarmCli
|
|
|
12
12
|
@client = client
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
def call(prompt:, repo_override:, name_override:)
|
|
15
|
+
def call(prompt:, repo_override:, name_override:, template_override: nil)
|
|
16
16
|
repo, branch, error = run_preflight(repo_override)
|
|
17
17
|
return error if error
|
|
18
18
|
|
|
19
|
+
template_id, template_error = resolve_template_id(template_override)
|
|
20
|
+
return template_error if template_error
|
|
21
|
+
|
|
19
22
|
push_result = @git.run("push", "-u", "origin", "HEAD")
|
|
20
23
|
return failure(push_result.stderr.strip) unless push_result.success?
|
|
21
24
|
|
|
22
|
-
create_task(repo: repo, branch: branch, prompt: prompt, name_override: name_override
|
|
25
|
+
create_task(repo: repo, branch: branch, prompt: prompt, name_override: name_override,
|
|
26
|
+
template_id: template_id)
|
|
23
27
|
rescue Faraday::Error => e
|
|
24
28
|
failure(parse_api_error(e))
|
|
25
29
|
end
|
|
@@ -97,13 +101,22 @@ module SchwarmCli
|
|
|
97
101
|
nil
|
|
98
102
|
end
|
|
99
103
|
|
|
100
|
-
def
|
|
104
|
+
def resolve_template_id(ref)
|
|
105
|
+
[TemplateResolver.new(client: @client).resolve(ref), nil]
|
|
106
|
+
rescue TemplateResolver::ResolutionError => e
|
|
107
|
+
[nil, failure(e.message)]
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def create_task(repo:, branch:, prompt:, name_override:, template_id:)
|
|
101
111
|
response = @client.tasks.create(
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
112
|
+
**{
|
|
113
|
+
name: name_override || branch,
|
|
114
|
+
branch_name: branch,
|
|
115
|
+
prompt: prompt,
|
|
116
|
+
status: "ready",
|
|
117
|
+
github_repository_id: repo["id"],
|
|
118
|
+
task_template_id: template_id
|
|
119
|
+
}.compact
|
|
107
120
|
)
|
|
108
121
|
data = response["data"]
|
|
109
122
|
Result.new(
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SchwarmCli
|
|
4
|
+
# Turns a user-provided `--template` reference into a task template ID.
|
|
5
|
+
#
|
|
6
|
+
# Accepted inputs:
|
|
7
|
+
# - a numeric template ID (looked up directly)
|
|
8
|
+
# - an exact template name (resolved via search + exact match)
|
|
9
|
+
class TemplateResolver
|
|
10
|
+
class ResolutionError < StandardError; end
|
|
11
|
+
|
|
12
|
+
def initialize(client:)
|
|
13
|
+
@client = client
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def resolve(ref)
|
|
17
|
+
return nil if blank?(ref)
|
|
18
|
+
|
|
19
|
+
ref = ref.to_s.strip
|
|
20
|
+
template = ref.match?(/\A\d+\z/) ? find_by_id(ref) : find_by_name(ref)
|
|
21
|
+
raise ResolutionError, "no schwarm task template matches `#{ref}`." if template.nil?
|
|
22
|
+
|
|
23
|
+
template["id"]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def blank?(ref)
|
|
29
|
+
ref.nil? || ref.to_s.strip.empty?
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def find_by_id(id)
|
|
33
|
+
@client.templates.find(id)["data"]
|
|
34
|
+
rescue Faraday::ResourceNotFound
|
|
35
|
+
nil
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def find_by_name(name)
|
|
39
|
+
response = @client.templates.list(query: name)
|
|
40
|
+
Array(response["data"]).find { |t| t["name"] == name }
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
data/lib/schwarm_cli/version.rb
CHANGED
data/lib/schwarm_cli.rb
CHANGED
|
@@ -5,6 +5,7 @@ require_relative "schwarm_cli/config"
|
|
|
5
5
|
require_relative "schwarm_cli/client"
|
|
6
6
|
require_relative "schwarm_cli/git"
|
|
7
7
|
require_relative "schwarm_cli/repository_resolver"
|
|
8
|
+
require_relative "schwarm_cli/template_resolver"
|
|
8
9
|
require_relative "schwarm_cli/hands_off_task"
|
|
9
10
|
require_relative "schwarm_cli/formatters/json"
|
|
10
11
|
require_relative "schwarm_cli/formatters/table"
|
data/schwarm-skill.md
CHANGED
|
@@ -86,6 +86,42 @@ EOF
|
|
|
86
86
|
will print the conflicting task ID. Archive or reset it first.
|
|
87
87
|
- The repository is auto-detected from `git remote get-url origin`. Use
|
|
88
88
|
`--repo <id>` if you need to override it (e.g. in a fork).
|
|
89
|
+
- Pass `--template <id-or-name>` to apply a task template to the handoff. The
|
|
90
|
+
value can be a template ID or its exact name.
|
|
91
|
+
|
|
92
|
+
### 1c. Hand off a WIP branch with follow-up tasks
|
|
93
|
+
|
|
94
|
+
**When:** You're handing off a WIP branch and want other tasks to run after it
|
|
95
|
+
on the same repo (e.g. add docs, cut a release PR, update a dashboard). The
|
|
96
|
+
handoff task starts immediately; the follow-ups wait until it's archived.
|
|
97
|
+
|
|
98
|
+
**Steps:**
|
|
99
|
+
1. Hand off the current branch first and note the task ID it prints:
|
|
100
|
+
```bash
|
|
101
|
+
schwarm tasks handoff --prompt "continue per HANDOFF.md"
|
|
102
|
+
# => Task a1b2c3 created (status: ready).
|
|
103
|
+
```
|
|
104
|
+
2. Create follow-up tasks as drafts depending on the handoff task ID:
|
|
105
|
+
```bash
|
|
106
|
+
schwarm tasks create --repo <REPO_ID> --name "Update docs" \
|
|
107
|
+
--prompt "Update README and CHANGELOG once the branch lands" --depends-on a1b2c3
|
|
108
|
+
schwarm tasks create --repo <REPO_ID> --name "Announce in #releases" \
|
|
109
|
+
--prompt "Post the summary to Slack" --depends-on a1b2c3
|
|
110
|
+
```
|
|
111
|
+
3. Start each follow-up — it will move to `waiting` until the handoff archives:
|
|
112
|
+
```bash
|
|
113
|
+
schwarm tasks start <FOLLOWUP_ID>
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**Watch for:**
|
|
117
|
+
- The handoff task is created with `status: ready` and runs immediately. You
|
|
118
|
+
don't need to start it.
|
|
119
|
+
- Follow-ups run on fresh worktrees off the repo's base branch by default, not
|
|
120
|
+
off the handoff branch. `--depends-on` keeps them in `waiting` until the
|
|
121
|
+
handoff task is archived, so by the time they start the handoff's changes are
|
|
122
|
+
already on the base branch.
|
|
123
|
+
- Pass `--repo <id>` on `tasks create` (handoff auto-detects it from `origin`,
|
|
124
|
+
but `create` does not).
|
|
89
125
|
|
|
90
126
|
### 2. Dispatch a DAG of tasks
|
|
91
127
|
|
|
@@ -192,9 +228,10 @@ must `start` again.
|
|
|
192
228
|
schwarm templates list
|
|
193
229
|
schwarm templates show <TEMPLATE_ID>
|
|
194
230
|
```
|
|
195
|
-
3. Create a task from a template
|
|
231
|
+
3. Create a task from a template. `--template` accepts either the template ID or
|
|
232
|
+
its exact name:
|
|
196
233
|
```bash
|
|
197
|
-
schwarm tasks create --repo <REPO_ID> --name "Apply template" --template <
|
|
234
|
+
schwarm tasks create --repo <REPO_ID> --name "Apply template" --template <TEMPLATE_ID_OR_NAME> --status ready
|
|
198
235
|
```
|
|
199
236
|
|
|
200
237
|
### 7. Manage recurring tasks
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: schwarm-cli
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Vincent Garrigues
|
|
@@ -123,6 +123,7 @@ files:
|
|
|
123
123
|
- lib/schwarm_cli/git.rb
|
|
124
124
|
- lib/schwarm_cli/hands_off_task.rb
|
|
125
125
|
- lib/schwarm_cli/repository_resolver.rb
|
|
126
|
+
- lib/schwarm_cli/template_resolver.rb
|
|
126
127
|
- lib/schwarm_cli/version.rb
|
|
127
128
|
- schwarm-skill.md
|
|
128
129
|
homepage: https://github.com/getdexter/schwarm
|