maf 0.2.0 → 0.3.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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +43 -0
  3. data/README.md +18 -1
  4. data/assets/agents-contract.md +2 -0
  5. data/assets/coord +145 -21
  6. data/assets/dispatcher +59 -13
  7. data/install.md +6 -1
  8. data/lib/maf/bootstrap/claude_settings.rb +17 -9
  9. data/lib/maf/bootstrap.rb +4 -0
  10. data/lib/maf/cli.rb +19 -9
  11. data/lib/maf/flow/effort_report.rb +20 -0
  12. data/lib/maf/flow/generator.rb +2 -1
  13. data/lib/maf/flow/hermes_env_setup.rb +46 -0
  14. data/lib/maf/flow/manifest.rb +1 -1
  15. data/lib/maf/flow/models.rb +11 -0
  16. data/lib/maf/flow/options.rb +29 -3
  17. data/lib/maf/flow/prompt_text.rb +6 -3
  18. data/lib/maf/flow/report.rb +6 -5
  19. data/lib/maf/flow/role_catalog.rb +1 -1
  20. data/lib/maf/flow/role_files.rb +5 -5
  21. data/lib/maf/flow/roster.rb +6 -3
  22. data/lib/maf/flow.rb +3 -1
  23. data/lib/maf/menu.rb +48 -14
  24. data/lib/maf/setup_agent/args.rb +16 -10
  25. data/lib/maf/setup_agent/dispatch.rb +2 -2
  26. data/lib/maf/setup_agent/launcher.rb +6 -4
  27. data/lib/maf/setup_agent/manifest.rb +9 -3
  28. data/lib/maf/setup_agent.rb +11 -11
  29. data/lib/maf/shared/harness/defaults.rb +10 -3
  30. data/lib/maf/shared/harnesses/claude.rb +6 -3
  31. data/lib/maf/shared/harnesses/codex.rb +39 -10
  32. data/lib/maf/shared/harnesses/cursor.rb +60 -4
  33. data/lib/maf/shared/harnesses/hermes.rb +21 -11
  34. data/lib/maf/shared/harnesses/opencode.rb +25 -2
  35. data/lib/maf/shared/roles.rb +4 -0
  36. data/lib/maf/team.rb +5 -4
  37. data/lib/maf/team_command.rb +3 -1
  38. data/lib/maf/untrack.rb +7 -0
  39. data/lib/maf/version.rb +1 -1
  40. data/lib/maf/worker_control.rb +12 -1
  41. data/lib/maf/worker_list.rb +83 -0
  42. data/templates/roles.yml +14 -0
  43. metadata +4 -1
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ # worker_list.rb - list the workers that run now: sessions and dispatchers.
4
+ require "json"
5
+ require "time"
6
+ require_relative "workers"
7
+ require_relative "shared/processes"
8
+
9
+ module Maf
10
+ # WorkerList shows each running worker process of the project. A worker
11
+ # can run twice, for example as a session and as a dispatcher.
12
+ class WorkerList
13
+ Row = Struct.new(:worker, :role, :harness, :mode, :pid, :started)
14
+ HEADER = %w[WORKER ROLE HARNESS MODE PID STARTED].freeze
15
+ LSTART = "%a %b %d %H:%M:%S %Y %z"
16
+
17
+ def initialize(root)
18
+ @root = root
19
+ @workers = Workers.at(root)
20
+ end
21
+
22
+ def run
23
+ rows = running
24
+ puts rows.empty? ? "No worker runs." : table([HEADER] + rows.map { |row| row.to_a.map(&:to_s) }), warnings(rows)
25
+ end
26
+
27
+ private
28
+
29
+ def running = (sessions + dispatchers + registered).uniq(&:pid).sort_by { |row| [row.worker, row.mode] }
30
+
31
+ def coord_dir = File.join(@root, ".maf", "coordination")
32
+ def records(dir, pattern) = Dir.glob(File.join(coord_dir, dir, pattern)).map { |path| [path, read(path)] }
33
+
34
+ def sessions
35
+ records("sessions", "*.maf.json").filter_map do |path, record|
36
+ row(record, "session") if session_live?(record["pid"], File.mtime(path))
37
+ end
38
+ end
39
+
40
+ def session_live?(pid, registered)
41
+ started = Shared::Processes.started_at(pid)
42
+ Shared::Processes.alive?(pid) && !started.empty? && Time.strptime("#{started} +0000", LSTART) <= registered
43
+ rescue ArgumentError
44
+ false
45
+ end
46
+
47
+ def dispatchers
48
+ records("presence", "*.json").filter_map do |_, entry|
49
+ row(entry, "dispatch") if entry["mode"] == "dispatch" && Shared::Processes.live?(entry)
50
+ end
51
+ end
52
+
53
+ def registered
54
+ @workers.all.filter_map do |worker, entry|
55
+ row(entry.merge("worker" => worker), "dispatch") if @workers.dispatcher?(worker)
56
+ end
57
+ end
58
+
59
+ def row(data, mode)
60
+ entry = @workers.find(data["worker"]).to_h
61
+ Row.new(data["worker"], data["role"] || entry["role"], data["harness"] || entry["harness"], mode,
62
+ data["pid"].to_i, Shared::Processes.started_at(data["pid"]))
63
+ end
64
+
65
+ def table(lines)
66
+ widths = lines.transpose.map { |column| column.map(&:size).max }
67
+ lines.map { |line| line.zip(widths).map { |text, width| text.ljust(width) }.join(" ").rstrip }
68
+ end
69
+
70
+ def warnings(rows)
71
+ twice = rows.group_by(&:worker).select { |_, list| list.size > 1 }
72
+ stopped = @workers.all.keys - rows.map(&:worker)
73
+ twice.map { |worker, list| "warning: #{worker} runs #{list.size} times (pids #{list.map(&:pid).join(", ")})" } +
74
+ (stopped.empty? ? [] : ["stopped: #{stopped.join(", ")}"])
75
+ end
76
+
77
+ def read(path)
78
+ JSON.parse(File.read(path))
79
+ rescue JSON::ParserError, SystemCallError
80
+ {}
81
+ end
82
+ end
83
+ end
data/templates/roles.yml CHANGED
@@ -4,6 +4,9 @@
4
4
  # the model with --model ROLE=MODEL. If the user does not choose a model,
5
5
  # claude roles get lib/maf/flow.rb's DEFAULT_MODELS entry (claude-opus-5-5).
6
6
  #
7
+ # `effort` is the default effort level. A role gets it when the harness lists
8
+ # the level. --effort ROLE=LEVEL overrides it. A lower level uses fewer tokens.
9
+ #
7
10
  # `description` is also the routing line in the architect's "Available roles"
8
11
  # list. Keep it short and specific to the role.
9
12
  #
@@ -42,6 +45,7 @@ roles:
42
45
  - If a message starts with "ESCALATION", a role cannot fix a problem. Tell the user in plain words:
43
46
  what failed, which task, and the impact. Give two or three options with a recommended one.
44
47
  Wait for the answer. Then send the answer to the role with `coord msg`.
48
+ If the escalation names a blocked task, run `coord unblock <id>` after you send the answer.
45
49
  - If the architect escalates a repeated review failure, forward the
46
50
  options to the user. Do not send a new goal until the user decides.
47
51
 
@@ -53,6 +57,7 @@ roles:
53
57
  - Process detail in reports. The user needs outcomes and decisions.
54
58
  - Optimistic status. Report blockers and failed checks as they are.
55
59
  model_hint: "Strongest reasoning and long context, conversational. Cloud: Claude Opus 5.5 (default for the claude harness), GPT-5.x."
60
+ effort: medium
56
61
  can_edit: false
57
62
 
58
63
  architect:
@@ -84,6 +89,8 @@ roles:
84
89
  Goal, Inputs, Out of scope, Acceptance, Report format.
85
90
  A worker drifts if a field is missing.
86
91
  - Write acceptance criteria as exact test files or commands. The worker runs each one before coord done.
92
+ - A message `BLOCKED task <id> (dependency)` waits for other work. Plan or order that work.
93
+ When it lands, run `coord unblock <id>`. A blocked task stays out of `coord next` until then.
87
94
  - If a review rejects the same kind of problem two times, stop the fix
88
95
  loop. Send the project manager two or three options with the cost of
89
96
  each option. A third patch of the same kind usually fails too.
@@ -96,6 +103,7 @@ roles:
96
103
  - Code in task specs. Describe behavior and constraints instead.
97
104
  - Trust in a worker report without a diff check.
98
105
  model_hint: "Strongest reasoning and long context. Cloud: Claude Opus 5.5 (default for the claude harness), GPT-5.x, deepseek-v4."
106
+ effort: high
99
107
  can_edit: false
100
108
 
101
109
  backend-developer:
@@ -123,6 +131,7 @@ roles:
123
131
  - Edits to a test that looks wrong. Report the test to the architect.
124
132
  - Claims about code that you did not read.
125
133
  model_hint: "A strong code model. A local Qwen3.8-27B is enough for well-scoped tasks; use a cloud coder for hard or large changes."
134
+ effort: medium
126
135
  can_edit: true
127
136
 
128
137
  frontend-developer:
@@ -149,6 +158,7 @@ roles:
149
158
  - Values that are hard-coded to make a test pass.
150
159
  - Visual changes outside the task scope.
151
160
  model_hint: "Same as backend-developer: local coder for scoped work, cloud coder for hard UI work."
161
+ effort: medium
152
162
  can_edit: true
153
163
 
154
164
  tester:
@@ -174,6 +184,7 @@ roles:
174
184
  - Assertions that only repeat the implementation.
175
185
  - Deleted or weakened tests. A test removal needs architect approval.
176
186
  model_hint: "Mechanical test work usually fits a local coder model; use cloud for subtle failure analysis."
187
+ effort: low
177
188
  can_edit: true
178
189
 
179
190
  reviewer:
@@ -216,6 +227,7 @@ roles:
216
227
  - Style comments that the project's linter already covers.
217
228
  - A warning or minor finding labeled critical to force another round.
218
229
  model_hint: "Judgment-heavy. Prefer a cloud model with strong review ability."
230
+ effort: high
219
231
  can_edit: false
220
232
 
221
233
  skeptic:
@@ -252,6 +264,7 @@ roles:
252
264
  - A warning or minor finding labeled critical to force another round.
253
265
  - Style comments. The reviewer and the linter cover style.
254
266
  model_hint: "Judgment-heavy. Use a different model family from reviewer and auditor, for example GPT-5.x if reviewer runs Claude. Different models miss different defects."
267
+ effort: high
255
268
  can_edit: false
256
269
 
257
270
  auditor:
@@ -286,4 +299,5 @@ roles:
286
299
  - A warning or minor finding labeled critical to force another round.
287
300
  - Style comments. The reviewer and the linter cover style.
288
301
  model_hint: "Judgment-heavy. Use a different model family from reviewer and skeptic, for example Gemini, Grok, or a strong local model. Different models miss different defects."
302
+ effort: high
289
303
  can_edit: false
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: maf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dominik Alberski
@@ -83,8 +83,10 @@ files:
83
83
  - lib/maf/flow/agent_links.rb
84
84
  - lib/maf/flow/bootstrapper.rb
85
85
  - lib/maf/flow/codex_hooks.rb
86
+ - lib/maf/flow/effort_report.rb
86
87
  - lib/maf/flow/generator.rb
87
88
  - lib/maf/flow/harness_linker.rb
89
+ - lib/maf/flow/hermes_env_setup.rb
88
90
  - lib/maf/flow/hermes_hook.rb
89
91
  - lib/maf/flow/hermes_hook_setup.rb
90
92
  - lib/maf/flow/hook_files.rb
@@ -178,6 +180,7 @@ files:
178
180
  - lib/maf/vm/template.rb
179
181
  - lib/maf/worker_archive.rb
180
182
  - lib/maf/worker_control.rb
183
+ - lib/maf/worker_list.rb
181
184
  - lib/maf/workers.rb
182
185
  - templates/role-stub.yml.erb
183
186
  - templates/roles.yml