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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f86723cf9675bb0de813b11efa16be17bd2b8bfa74bd9af1203130cdf7fda0f0
4
- data.tar.gz: 479a9e83426d1fb675b79dd5780b14264d7a6c8454ee30404c104743aed30fdd
3
+ metadata.gz: cb4e9030ccc6a70a2d35c94e5c2db414bae4b56550ae21128b2e3f612b56b6cf
4
+ data.tar.gz: 4c4bfd79d9b120f01764b4b482200757a5a3f4d1a1e8dba5c344486befebf48d
5
5
  SHA512:
6
- metadata.gz: 9e473284f4c066af2f5ed3a77cc365448574acd73a55e1f72e5d2eb94d1b11db5a95fc4fdaf23c498ecb721ef0f2f596ff753c1c869726446a66d6ae622cf167
7
- data.tar.gz: b3d2498b0dcea13e9ed75ea1ee865fdf25658a31a5552059cfb617efcead48600f46008fbd4f580766250daa6b99f38619412a4c4cfa32175f6736b7f45e7c3e
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 create_task(repo:, branch:, prompt:, name_override:)
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
- name: name_override || branch,
103
- branch_name: branch,
104
- prompt: prompt,
105
- status: "ready",
106
- github_repository_id: repo["id"]
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SchwarmCli
4
- VERSION = "0.1.5"
4
+ VERSION = "0.1.6"
5
5
  end
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 <TEMPLATE_ID> --status ready
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.5
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