maf 0.1.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 (136) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +11 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +411 -0
  5. data/assets/agents-contract.md +80 -0
  6. data/assets/analyst +240 -0
  7. data/assets/coord +2936 -0
  8. data/assets/dashboard +553 -0
  9. data/assets/dashboard.html +341 -0
  10. data/assets/dispatcher +1687 -0
  11. data/assets/doc-graph-refresh +286 -0
  12. data/assets/env.sh +6 -0
  13. data/assets/git-hooks/post-commit +7 -0
  14. data/assets/git-hooks/post-merge +7 -0
  15. data/assets/git-hooks/pre-commit +32 -0
  16. data/assets/harness-hooks/board-watch-opencode.js +87 -0
  17. data/assets/harness-hooks/board-watch.rb +286 -0
  18. data/assets/harness-hooks/context-watch.rb +268 -0
  19. data/assets/harness-hooks/next-task-hermes.sh +48 -0
  20. data/assets/harness-hooks/next-task.rb +97 -0
  21. data/assets/harness-hooks/session-guard.rb +128 -0
  22. data/assets/taskrc.append +11 -0
  23. data/assets/vault +224 -0
  24. data/assets/worktree-env.example.rb +26 -0
  25. data/exe/maf +14 -0
  26. data/install.md +326 -0
  27. data/lib/maf/bootstrap/claude_settings.rb +55 -0
  28. data/lib/maf/bootstrap/dependencies.rb +37 -0
  29. data/lib/maf/bootstrap/git_hook_planner.rb +68 -0
  30. data/lib/maf/bootstrap/global_taskrc_warning.rb +33 -0
  31. data/lib/maf/bootstrap/graph_home.rb +62 -0
  32. data/lib/maf/bootstrap/hook_merger.rb +53 -0
  33. data/lib/maf/bootstrap/installer.rb +66 -0
  34. data/lib/maf/bootstrap/layout_planner.rb +18 -0
  35. data/lib/maf/bootstrap/marked_block.rb +44 -0
  36. data/lib/maf/bootstrap/memory_branch.rb +77 -0
  37. data/lib/maf/bootstrap/options.rb +34 -0
  38. data/lib/maf/bootstrap/project.rb +77 -0
  39. data/lib/maf/bootstrap/script_planner.rb +81 -0
  40. data/lib/maf/bootstrap/text_planner.rb +42 -0
  41. data/lib/maf/bootstrap/vault_starter.rb +41 -0
  42. data/lib/maf/bootstrap/writer.rb +69 -0
  43. data/lib/maf/bootstrap.rb +162 -0
  44. data/lib/maf/budget.rb +59 -0
  45. data/lib/maf/cli.rb +135 -0
  46. data/lib/maf/env_exclude.rb +23 -0
  47. data/lib/maf/flow/agent_links.rb +79 -0
  48. data/lib/maf/flow/bootstrapper.rb +36 -0
  49. data/lib/maf/flow/codex_hooks.rb +50 -0
  50. data/lib/maf/flow/generator.rb +63 -0
  51. data/lib/maf/flow/harness_linker.rb +37 -0
  52. data/lib/maf/flow/hermes_hook.rb +48 -0
  53. data/lib/maf/flow/hermes_hook_setup.rb +69 -0
  54. data/lib/maf/flow/hook_files.rb +16 -0
  55. data/lib/maf/flow/hook_installer.rb +33 -0
  56. data/lib/maf/flow/legacy_codex_hook.rb +71 -0
  57. data/lib/maf/flow/manifest.rb +51 -0
  58. data/lib/maf/flow/mcp_config.rb +72 -0
  59. data/lib/maf/flow/mcp_installer.rb +45 -0
  60. data/lib/maf/flow/models.rb +61 -0
  61. data/lib/maf/flow/options.rb +65 -0
  62. data/lib/maf/flow/prompt_builder.rb +85 -0
  63. data/lib/maf/flow/prompt_text.rb +263 -0
  64. data/lib/maf/flow/report.rb +89 -0
  65. data/lib/maf/flow/role_catalog.rb +40 -0
  66. data/lib/maf/flow/role_files.rb +72 -0
  67. data/lib/maf/flow/role_stub.rb +38 -0
  68. data/lib/maf/flow/roster.rb +28 -0
  69. data/lib/maf/flow/validator.rb +38 -0
  70. data/lib/maf/flow/workflow.rb +28 -0
  71. data/lib/maf/flow.rb +84 -0
  72. data/lib/maf/local_exclude.rb +53 -0
  73. data/lib/maf/menu.rb +101 -0
  74. data/lib/maf/migrate/moves.rb +44 -0
  75. data/lib/maf/migrate/rewrites.rb +53 -0
  76. data/lib/maf/migrate/role_files.rb +35 -0
  77. data/lib/maf/migrate/runner.rb +66 -0
  78. data/lib/maf/migrate/worktrees.rb +65 -0
  79. data/lib/maf/migrate.rb +62 -0
  80. data/lib/maf/prompt.rb +40 -0
  81. data/lib/maf/retire.rb +116 -0
  82. data/lib/maf/role_limits.rb +49 -0
  83. data/lib/maf/setup_agent/args.rb +57 -0
  84. data/lib/maf/setup_agent/dispatch.rb +44 -0
  85. data/lib/maf/setup_agent/hermes_launcher.rb +34 -0
  86. data/lib/maf/setup_agent/hermes_skill.rb +26 -0
  87. data/lib/maf/setup_agent/launcher.rb +85 -0
  88. data/lib/maf/setup_agent/manifest.rb +35 -0
  89. data/lib/maf/setup_agent/project.rb +9 -0
  90. data/lib/maf/setup_agent/role_file.rb +30 -0
  91. data/lib/maf/setup_agent/runtime_hooks.rb +37 -0
  92. data/lib/maf/setup_agent/worktree.rb +50 -0
  93. data/lib/maf/setup_agent.rb +111 -0
  94. data/lib/maf/shared/git_exclude.rb +33 -0
  95. data/lib/maf/shared/git_identity.rb +41 -0
  96. data/lib/maf/shared/peak_rate.rb +20 -0
  97. data/lib/maf/shared/processes.rb +31 -0
  98. data/lib/maf/shared/project.rb +34 -0
  99. data/lib/maf/shared/roles.rb +19 -0
  100. data/lib/maf/team.rb +114 -0
  101. data/lib/maf/team_command.rb +73 -0
  102. data/lib/maf/uninstall/claude_settings.rb +40 -0
  103. data/lib/maf/uninstall/codex_hooks.rb +18 -0
  104. data/lib/maf/uninstall/commit_guard.rb +16 -0
  105. data/lib/maf/uninstall/coordination.rb +15 -0
  106. data/lib/maf/uninstall/doc_graph_hooks.rb +38 -0
  107. data/lib/maf/uninstall/git.rb +13 -0
  108. data/lib/maf/uninstall/local_files.rb +33 -0
  109. data/lib/maf/uninstall/manifest.rb +29 -0
  110. data/lib/maf/uninstall/marked_files.rb +37 -0
  111. data/lib/maf/uninstall/mcp_entries.rb +43 -0
  112. data/lib/maf/uninstall/notes.rb +31 -0
  113. data/lib/maf/uninstall/owned.rb +12 -0
  114. data/lib/maf/uninstall/role_files.rb +51 -0
  115. data/lib/maf/uninstall/runner.rb +67 -0
  116. data/lib/maf/uninstall/scripts.rb +35 -0
  117. data/lib/maf/uninstall/vault_watcher.rb +21 -0
  118. data/lib/maf/uninstall/worktrees.rb +30 -0
  119. data/lib/maf/uninstall.rb +59 -0
  120. data/lib/maf/untrack.rb +90 -0
  121. data/lib/maf/version.rb +5 -0
  122. data/lib/maf/worker_archive.rb +63 -0
  123. data/lib/maf/worker_control.rb +137 -0
  124. data/lib/maf/workers.rb +37 -0
  125. data/lib/maf.rb +5 -0
  126. data/templates/claude.md.erb +16 -0
  127. data/templates/codex.md.erb +7 -0
  128. data/templates/hermes.md.erb +12 -0
  129. data/templates/opencode.md.erb +24 -0
  130. data/templates/role-stub.yml.erb +15 -0
  131. data/templates/roles.yml +289 -0
  132. data/templates/workflows/panel.md +20 -0
  133. data/templates/workflows/plan-review.md +9 -0
  134. data/templates/workflows/simple.md +4 -0
  135. data/templates/workflows/tdd.md +8 -0
  136. metadata +193 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 4cdbedeaf3c68e4b2aa40939c8f006f846d0d044531f2c6d53e01cddf4d9e45d
4
+ data.tar.gz: e90a24b66c78fd7cc493e493f722b25a5803430967b2cae0de46202befaf12b2
5
+ SHA512:
6
+ metadata.gz: ee79aa5c928c7be62ed39cdcf2904f7905b6e33189c31f19b7badd522cd0600431d6b39faebf72c7f60caf951ddbb577efc6d2a1fc167145f4f2503665ffe256
7
+ data.tar.gz: 0aa9875967605035e251dab51a6ad097dc80c428cda40a8db8abfad99d0cb5381d92da1c5b7e9dc5b4daa5d7263e670655150100a40f70fb0ec9369b35f868fe
data/CHANGELOG.md ADDED
@@ -0,0 +1,11 @@
1
+ # Changelog
2
+
3
+ ## [Unreleased]
4
+
5
+ ## [0.1.0] - 2026-10-08
6
+
7
+ - First release as a gem: `gem install maf`.
8
+ - All code is in the `Maf` module.
9
+ - The command moved from `bin/maf` to `exe/maf`. `bin/maf` stays for the links
10
+ that point to it. A later version removes it.
11
+ - New commands: `maf version` and `maf guide` (prints the agent setup guide).
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2026 Dominik Alberski
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,411 @@
1
+ # multi_agent_flow
2
+
3
+ Coordination layer for running several AI coding agents (opencode, Claude Code,
4
+ Hermes, Codex) in parallel on one repository, each in its own terminal.
5
+
6
+ Three pillars:
7
+
8
+ | Pillar | Implementation |
9
+ |---|---|
10
+ | Communication | Taskwarrior task board + `.maf/coordination/` inbox, via the `coord` CLI |
11
+ | Resource control | `mkdir`-based locks — no `flock`, works on macOS and Linux |
12
+ | Shared memory | graphify knowledge graph + Obsidian vault, served over MCP |
13
+
14
+ The whole layer is **CLI + files**: every harness uses it identically; no GUI or
15
+ vendor dependency.
16
+
17
+ ---
18
+
19
+ ## Requirements
20
+
21
+ The `maf` gem holds the flow. Install these tools yourself:
22
+
23
+ | Tool | Why | Install |
24
+ |---|---|---|
25
+ | Ruby 3.0+ | runs `maf`, `coord`, and the other scripts | macOS: `brew install mise && mise install ruby`. Linux: your package manager or [mise](https://mise.jdx.dev) |
26
+ | git | worktrees, hooks, the local exclude file | macOS: `xcode-select --install` or `brew install git`. Linux: `apt install git` |
27
+ | Taskwarrior | the task board | macOS: `brew install task`. Linux: `apt install taskwarrior` |
28
+ | One or more harnesses | the agents | [Claude Code](https://docs.claude.com/en/docs/claude-code), [Codex](https://github.com/openai/codex), [opencode](https://opencode.ai), [Hermes](https://github.com/NousResearch/hermes-agent) |
29
+ | graphify (optional) | the shared knowledge graph | `uv tool install graphifyy` |
30
+
31
+ Install the gem:
32
+
33
+ ```sh
34
+ gem install maf
35
+ maf version
36
+ ```
37
+
38
+ Upgrade the gem. Then run `maf update` in each project: it replaces the flow files with the new versions.
39
+
40
+ ```sh
41
+ gem update maf
42
+ cd ~/Projects/my-app && maf update
43
+ ```
44
+
45
+ ## Fast path — agent-driven
46
+
47
+ 1. Install the gem: `gem install maf`.
48
+ 2. Open any AI coding agent in your project folder and say:
49
+
50
+ > Run `maf guide`. Read the output and implement it.
51
+
52
+ The agent asks which harnesses and roles to use, runs `maf add`, and prints
53
+ the `maf start` commands to start each session.
54
+
55
+ `maf guide` prints **[install.md](install.md)**: the exact instructions that the agent follows.
56
+
57
+ ## Manual path - the maf command
58
+
59
+ Run `maf` in the project root.
60
+
61
+ ```sh
62
+ cd ~/Projects/my-app
63
+ maf roles # list the roles
64
+ maf add claude:architect opencode:backend-developer # install the flow and add agents
65
+ maf start claude architect # start one agent in its worktree
66
+ maf help # all commands
67
+ ```
68
+
69
+ Run `maf` without a command to use the interactive menu. The menu asks for
70
+ each value: harness, roles, models, and the agent to start.
71
+
72
+ ---
73
+
74
+ ## Project layout
75
+
76
+ The flow keeps every file that it owns in one folder, `.maf/`, in the project.
77
+ The knowledge graph is the exception: it is project knowledge, not tooling, so it
78
+ lives in `graphify-out/` at the project root, where graphify looks by default.
79
+
80
+ ```
81
+ .maf/
82
+ bin/ coord, dispatcher, vault, dashboard, analyst, doc-graph-refresh
83
+ lib/maf/shared/ code that the scripts in bin/ load (maf update replaces it)
84
+ coordination/ task board, inbox, locks, presence, sessions, hooks, logs
85
+ worktrees/ one git worktree per worker
86
+ agents/ role files: claude/, opencode/, codex/
87
+ claude/ settings.json: the Claude Code hooks (maf start passes --settings)
88
+ mcp/ the graphify MCP server for Claude Code and opencode
89
+ config.json the agents and settings of the project
90
+ roles.yml project roles (you write it; maf role add NAME)
91
+ workflow.md stage instructions for the architect (you write it)
92
+ env.sh source it: puts .maf/bin on PATH
93
+ graphify-out/ knowledge graph (excluded from git; each worktree has a symlink to it)
94
+ memory/ work memory notes: a worktree of the orphan branch maf/memory (ADR 0006)
95
+ obsidian/ generated Obsidian vault
96
+ ```
97
+
98
+ maf is a tool, not a part of the project. Nothing that runs maf goes into git:
99
+ `.maf/` and each link and plugin that maf creates are listed in `.git/info/exclude`,
100
+ which is local to the clone. maf never edits a file that the project tracks.
101
+
102
+ The project keeps what the agents make, also after `maf uninstall`:
103
+
104
+ | Path | What it is |
105
+ |---|---|
106
+ | the code | The work of the agents, landed on the goal branches. |
107
+ | `GLOSSARY.md` | The domain glossary. The project manager drafts it. A worker commits it on the architect's task. |
108
+ | `docs/decisions/` | ADRs. The architect decides them. A worker commits them. |
109
+
110
+ Local files that a harness or git reads outside `.maf/`:
111
+
112
+ | Path | Reason |
113
+ |---|---|
114
+ | `.git/hooks/*` | Git reads them there. |
115
+ | `.git/info/exclude` | Keeps the flow out of git in this clone. |
116
+ | `.claude/agents/`, `.opencode/agents/`, `.codex/prompts/` | Symlinks into `.maf/agents/<harness>/`. |
117
+ | `.opencode/plugins/board-watch.js` | opencode reads it there. |
118
+ | `.codex/hooks.json` | Codex reads it there. Excluded when the project does not track it. |
119
+ | `~/.hermes/skills/<project>-<role>/SKILL.md` | Hermes reads it there. |
120
+
121
+ Claude Code gets the hooks from `.maf/claude/settings.json` (`--settings`) and the
122
+ graphify MCP server from `.maf/mcp/claude.json` (`--mcp-config`). opencode gets the
123
+ server from `.maf/mcp/opencode.json` (`OPENCODE_CONFIG`). `maf start` and the
124
+ dispatcher pass these files. The project's `.claude/settings.json`, `.mcp.json`,
125
+ `opencode.json`, `AGENTS.md`, and `CLAUDE.md` stay as they are.
126
+
127
+ MAF installs Codex hooks in the project `.codex/hooks.json` file.
128
+ Hooks act only on sessions that `maf start` registers.
129
+ Each hook checks the launch token, process, worktree, role, worker, board, and harness session ID.
130
+ An independent session does not activate hooks, even with inherited coordination variables.
131
+ `maf update` disables the legacy global Codex hook and removes only its registration.
132
+ Other global hooks stay.
133
+ Restart workers with `maf start` after the update.
134
+
135
+ A project with the old layout runs `maf migrate` once. See the migration
136
+ section of [USER_MANUAL.md](USER_MANUAL.md).
137
+
138
+ ---
139
+
140
+ ## Documentation
141
+
142
+ | File | Audience | What it covers |
143
+ |---|---|---|
144
+ | **[docs/flow-glossary.md](docs/flow-glossary.md)** | Everyone | Flow terms: harness, role, worker, agent, task, message, claim, lock, hooks. [docs/flow-cli-names.md](docs/flow-cli-names.md) lists their names in code and CLI |
145
+ | **[GETTING_STARTED.md](GETTING_STARTED.md)** | First-time user | Concepts, prerequisites, manual install, basic workflow |
146
+ | **[USER_MANUAL.md](USER_MANUAL.md)** | Setting up a real team | Full install (maf), all harnesses, dispatcher, monitoring |
147
+ | **[install.md](install.md)** | An AI coding agent | Interactive wizard: asks the user for harnesses/roles, runs `maf add` |
148
+ | **[docs/out-of-scope.md](docs/out-of-scope.md)** | Contributor | Requests that the project rejects on purpose, with the reason |
149
+ | **[SKILL.md](SKILL.md)** | Agent skill loader | Self-contained portable skill (frontmatter + full API reference) |
150
+
151
+ ---
152
+
153
+ ## Contents
154
+
155
+ ```
156
+ multi_agent_flow/
157
+ install.md # agent instruction: interactive setup wizard
158
+ SKILL.md # portable skill for agent skill loaders
159
+ README.md # this file
160
+ docs/flow-glossary.md # flow terms
161
+ docs/flow-cli-names.md # code and CLI name of each flow term
162
+ GETTING_STARTED.md # first-time walkthrough (concepts + manual setup)
163
+ USER_MANUAL.md # full team setup reference
164
+ maf.gemspec # the gem: files, version, the webrick dependency
165
+ Gemfile # development gems: rake, minitest, rubocop
166
+ CHANGELOG.md # changes per version
167
+ exe/
168
+ maf # the maf command line tool (gem install maf puts it on PATH)
169
+ bin/
170
+ maf # old path of the command; loads exe/maf
171
+ setup # bundle install
172
+ console # irb with maf loaded
173
+ lib/maf.rb # require "maf" loads the command line tool
174
+ lib/maf/
175
+ version.rb # Maf::VERSION
176
+ cli.rb # maf subcommands
177
+ menu.rb # interactive menu (maf without a command)
178
+ prompt.rb # numbered terminal questions for the menu
179
+ flow.rb # generates harness-specific role files + installs coordination layer
180
+ bootstrap.rb # idempotent coordination layer installer
181
+ setup_agent.rb # maf start: worktree + harness launch
182
+ uninstall.rb # removes the flow from a project; keeps graphify-out/
183
+ migrate.rb # maf migrate: moves an old-layout install into .maf/
184
+ team.rb # maf prepare: adds or replaces one worker
185
+ team_command.rb # maf team: shows the team, or sets its budget
186
+ retire.rb # maf retire: removes one worker and archives its state
187
+ worker_control.rb # maf worker: stops, starts, or restarts one worker
188
+ flow/role_catalog.rb # merges .maf/roles.yml over the built-in roles
189
+ flow/workflow.rb # reads .maf/workflow.md for the architect prompt
190
+ flow/mcp_config.rb # writes the graphify MCP server into .maf/mcp/
191
+ untrack.rb # maf untrack: removes an older install from git
192
+ local_exclude.rb # the flow block in .git/info/exclude
193
+ shared/ # stdlib-only code that the maf CLI and the scripts share (installed as .maf/lib/maf/shared/)
194
+ scripts/
195
+ check.rb # repo consistency check (UDA sync, markers, script signatures)
196
+ templates/
197
+ roles.yml # role definitions + model hints
198
+ role-stub.yml.erb # stub that maf role add writes
199
+ workflows/ # default workflows: simple, plan-review, tdd, panel
200
+ opencode.md.erb # role file templates per harness
201
+ claude.md.erb
202
+ codex.md.erb
203
+ hermes.md.erb
204
+ assets/
205
+ coord # coordination CLI (Ruby)
206
+ dispatcher # polls task board + inbox, starts one-shot agents (Ruby)
207
+ vault # graphify + Obsidian + MCP watcher control, graph age (Ruby)
208
+ dashboard # web dashboard: workers table with actions, alerts, board (Ruby/WEBrick)
209
+ analyst # asks a small model for token hints about one worker (dashboard analyze button)
210
+ doc-graph-refresh # graphify rebuild runner called by the git hooks (Ruby)
211
+ env.sh # shell environment: .maf/bin on PATH (installed as .maf/env.sh)
212
+ git-hooks/ # pre-commit guard, post-commit/post-merge refresh blocks
213
+ taskrc.append # Taskwarrior UDA block
214
+ agents-contract.md # coordination contract at the end of each role prompt
215
+ harness-hooks/ # next-task, board-watch, session-guard, and context-watch scripts, and the opencode plugin
216
+ test/
217
+ coord_test.rb # behavioral tests for the coord CLI
218
+ installer_test.rb # tests for bootstrap.rb, flow.rb, setup_agent.rb
219
+ maf_test.rb # tests for the maf command
220
+ dashboard_test.rb # tests for the dashboard data
221
+ dispatcher_test.rb # tests for the dispatcher
222
+ uninstaller_test.rb # tests for uninstall.rb
223
+ migrate_test.rb # tests for migrate.rb
224
+ roles_workflow_test.rb # tests for project roles and the workflow
225
+ graph_age_test.rb # tests for vault age and the graph prompt rules
226
+ mcp_test.rb # tests for the MCP server wiring
227
+ doc_graph_refresh_test.rb # tests for the doc-graph refresh script
228
+ board_watch_test.rb # tests for the board watcher
229
+ context_watch_test.rb # tests for the context-watch hook
230
+ hook_session_test.rb # tests for session isolation
231
+ hook_config_test.rb # tests for project hooks
232
+ worker_control_test.rb # tests for maf worker
233
+ untrack_test.rb # tests for maf untrack
234
+ analyst_test.rb # tests for the analyst
235
+ shared_test.rb # tests for lib/maf/shared/
236
+ gemspec_test.rb # tests that the gem holds every runtime file
237
+ ```
238
+
239
+ ---
240
+
241
+ ## Use as a skill
242
+
243
+ Copy or symlink this directory into a skills location so agents can discover it.
244
+ The skill loader matches the folder name to `name:` in the frontmatter; the
245
+ installed folder must be `multi-agent-flow` (hyphen, not underscore):
246
+
247
+ ```sh
248
+ cp -R "$PWD" ~/.config/opencode/skills/multi-agent-flow
249
+ # or, for Claude Code:
250
+ cp -R "$PWD" ~/.claude/skills/multi-agent-flow
251
+ ```
252
+
253
+ The skill runs the `maf` command. Install the gem first: `gem install maf`.
254
+ Restart the agent to load the skill. You can also hand `SKILL.md` plus `assets/`
255
+ to any agent as direct context.
256
+
257
+ ---
258
+
259
+ ## Doc-graph refresh
260
+
261
+ A commit or merge that changes a markdown file refreshes the shared knowledge
262
+ graph. `maf add` appends a flow block to the `post-commit` and `post-merge`
263
+ hooks. The block starts `.maf/bin/doc-graph-refresh` detached, so the commit
264
+ returns at once.
265
+
266
+ The refresh runs `graphify extract . --backend gemini` and then
267
+ `graphify export obsidian --dir graphify-out/obsidian`. The graph lives in `graphify-out/`
268
+ at the project root. It builds in a temp dir and swaps the derived files on
269
+ success, so a failed extract keeps the old graph. The swap never replaces
270
+ `graphify-out/memory/` or `graphify-out/obsidian/`. It then runs `graphify reflect` on the
271
+ saved notes. It needs `GEMINI_API_KEY`.
272
+ Without the key it logs a skip in `.maf/coordination/doc-graph.log` and exits. A
273
+ non-markdown commit makes no LLM call. A refresh started in a worktree writes
274
+ the shared graph in the main checkout.
275
+
276
+ ---
277
+
278
+ ## Contributor reference
279
+
280
+ After editing the UDA block or the worktree-path formula:
281
+
282
+ ```sh
283
+ ruby scripts/check.rb
284
+ ```
285
+
286
+ Verifies: the UDA block in `assets/coord` matches `assets/taskrc.append`; the
287
+ markers are present; the worktree path formula is identical in `assets/coord`
288
+ and `lib/maf/setup_agent/worktree.rb`; each script carries its signature; and the
289
+ literals that the standalone scripts share (lead roles, read-only toolsets,
290
+ the report format, the presence start time) are identical.
291
+
292
+ Install the development gems once:
293
+
294
+ ```sh
295
+ bin/setup # bundle install
296
+ ```
297
+
298
+ Run the checks and all tests:
299
+
300
+ ```sh
301
+ bundle exec rake # scripts/check.rb, RuboCop, then all tests
302
+ bundle exec rake lint # RuboCop only
303
+ bundle exec rake test TEST=test/coord_test.rb # one test file
304
+ ```
305
+
306
+ To use maf from the clone, link `exe/maf` into a folder on `PATH`:
307
+
308
+ ```sh
309
+ ln -sf "$PWD/exe/maf" ~/.local/bin/maf
310
+ ```
311
+
312
+ Build and install the gem from the clone:
313
+
314
+ ```sh
315
+ bundle exec rake build # writes pkg/maf-VERSION.gem
316
+ bundle exec rake install # builds and installs the gem
317
+ ```
318
+
319
+ To release, change `Maf::VERSION` in `lib/maf/version.rb` and add a
320
+ `CHANGELOG.md` entry.
321
+
322
+ RuboCop (pinned in the `Gemfile`) uses `.rubocop.yml`. It sets the
323
+ size rules: a class at most 100 lines, a method at most 5 lines and 4
324
+ parameters, a line at most 120 characters. `.rubocop_todo.yml` lists the code
325
+ that broke a rule before the config existed. Fix an entry, then delete it.
326
+ Do not add new entries.
327
+
328
+ `rake test` runs each test file in its own process, in parallel, and prints the
329
+ output of a failed file only. It unsets the variables below for each test.
330
+
331
+ An agent session exports `TASKRC` and `COORD_DIR` for the shared board. Unset
332
+ them when you run a test file directly, so a test never writes to that board:
333
+
334
+ ```sh
335
+ env -u TASKRC -u COORD_DIR -u COORD_ROLE -u COORD_WORKER ruby test/coord_test.rb
336
+ ```
337
+
338
+ ```sh
339
+ ruby test/coord_test.rb # covers the coord CLI
340
+ ruby test/installer_test.rb # covers bootstrap.rb, flow.rb, setup_agent.rb
341
+ ruby test/uninstaller_test.rb # covers uninstall.rb
342
+ ruby test/migrate_test.rb # covers migrate.rb
343
+ ruby test/roles_workflow_test.rb # covers project roles and the workflow
344
+ ruby test/graph_age_test.rb # covers vault age and the graph prompt rules
345
+ ruby test/mcp_test.rb # covers the MCP server wiring
346
+ ruby test/maf_test.rb # covers the maf command
347
+ ruby test/dashboard_test.rb # covers the dashboard data
348
+ ruby test/doc_graph_refresh_test.rb # covers the doc-graph refresh
349
+ ruby test/hook_session_test.rb # covers session isolation
350
+ ruby test/hook_config_test.rb # covers project hooks and legacy hook removal
351
+ ruby test/dispatcher_test.rb # covers the dispatcher
352
+ ruby test/board_watch_test.rb # covers the board watcher
353
+ ruby test/context_watch_test.rb # covers the context-watch hook
354
+ ruby test/worker_control_test.rb # covers maf worker
355
+ ruby test/untrack_test.rb # covers maf untrack
356
+ ruby test/analyst_test.rb # covers the analyst
357
+ ruby test/shared_test.rb # covers lib/maf/shared/
358
+ ```
359
+
360
+ Minitest, stdlib only. Tests that require `task`, `git`, or `node` skip (exit 0)
361
+ when those tools are absent. The dashboard tests need the `webrick` gem.
362
+ CI (`.github/workflows/test.yml`) installs all of them and runs the checks and
363
+ tests on Linux and macOS, and RuboCop, for each push to `main` and each pull
364
+ request.
365
+
366
+ ---
367
+
368
+ ## Design notes
369
+
370
+ - **Taskwarrior is the single source of truth**, in a project-local database
371
+ (`.maf/coordination/taskdata`, via `.maf/coordination/taskrc`) — never the user's
372
+ global `~/.task`. Two projects on this flow never share one board.
373
+ `coord board`/`export` are read-only projections.
374
+ - **Agents never call `task` directly.** `coord` keeps the protocol stable and
375
+ lets the storage backend change later.
376
+ - **Terminology:** see [docs/flow-glossary.md](docs/flow-glossary.md). One role can run as several
377
+ workers. `claim` is atomic, so two workers cannot take the same task.
378
+ - **A claim is a lease.** Idle past `COORD_LEASE_TTL` seconds (default 4 hours)
379
+ it becomes claimable again without `--force`. `coord unclaim` releases one on
380
+ demand.
381
+ - **Worktrees live inside the project** at `.maf/worktrees/<role>-<worker_id>`.
382
+ `.maf/worktrees/` is excluded from git. In each worktree, run `source .maf/env.sh` so
383
+ `COORD_DIR` and `TASKRC` point at the main project; every worktree shares one
384
+ `.maf/coordination/` dir and one task board.
385
+ - **Scope overlap** is checked on `coord add` (warning) and `coord conflicts`
386
+ (report). It is a path-prefix heuristic, not a full glob matcher. Scope is
387
+ advisory: nothing but agent discipline stops a write outside it, except that
388
+ roles with `can_edit: false` get a restricted tool grant where the harness
389
+ supports one (Claude Code, opencode, Hermes), and the git `pre-commit` guard
390
+ refuses their commits.
391
+ - **The `ollama` lock** is required when one local model host serves several
392
+ agents. Exclusion is TTL-based: coord stores no pid. A lock is reclaimed once its
393
+ TTL elapses (default 3600s), even if the holder is still alive. A killed
394
+ holder keeps the lock until the TTL elapses.
395
+ - **The `project-manager` role** is the user's proxy: the user talks to it, it
396
+ creates goals (`coord goal add`), sends them to the architect, and relays the report back. Without
397
+ `project-manager`, the user talks to the architect directly.
398
+ - **Rejected requests are logged.** When you reject a request on purpose, add
399
+ an entry to [docs/out-of-scope.md](docs/out-of-scope.md): the request, the
400
+ date, the source, and the reason. Read the log before you propose a feature.
401
+ - **UI is deliberately deferred**: Obsidian (Kanban/Dataview) or
402
+ `taskwarrior-tui` can read the same data without any agent changes.
403
+
404
+ ---
405
+
406
+ ## Acknowledgements
407
+
408
+ - The `panel` workflow and the `skeptic` and `auditor` roles come from
409
+ [shipyard](https://github.com/esse/shipyard) by Piotr Szmielew. Shipyard sends
410
+ a plan and a branch to adversarial reviewers from different model families.
411
+ The rules for critical findings and cited lines also come from shipyard.
@@ -0,0 +1,80 @@
1
+ <!-- >>> multi-agent-flow >>> -->
2
+ ## Multi-agent coordination
3
+
4
+ This project uses `coord`, a shared task board for several coding agents.
5
+ Run `source .maf/env.sh` once. It puts `coord` on `PATH` and points `COORD_DIR` at the shared board.
6
+ Use `coord`. Never use raw `task`.
7
+ Your role file holds your work loop. This section holds the terms and rules that all roles share.
8
+
9
+ ### Terms
10
+
11
+ - A role is a project function, for example `backend-developer`. A task belongs to a role.
12
+ - A worker is one instance of a role, for example `backend-1`. `COORD_ROLE` and `COORD_WORKER` identify you.
13
+ - A goal is one user-visible outcome. A goal has the branch `goal/<short-id>`.
14
+ - A task is one part of a goal. A worker does the task on the branch `task/<short-id>`.
15
+ - The lead roles are the project manager and the architect. A lead role never claims a task and never commits.
16
+ - Use the terms of the project glossary, `GLOSSARY.md` at the repository root.
17
+
18
+ ### Hierarchy
19
+
20
+ If the project has a project manager, the user talks only to the project manager.
21
+ The project manager sends each goal to the architect.
22
+ The architect splits the goal into tasks, lands the done tasks, and reports back.
23
+ Workers never talk to the user. Workers ask the architect with `coord msg`.
24
+
25
+ ### Commands
26
+
27
+ ```
28
+ coord show ID # one task: its fields and annotations (the task spec)
29
+ coord next [ROLE] [--wait] | --mine # unclaimed tasks, or your claimed tasks
30
+ coord claim ID | start-task ID | done ID # take a task, check out its branch, finish it
31
+ coord annotate ID TEXT # add a note to a task
32
+ coord lesson ID dead_end|corrected TEXT # an approach that failed, or the right way: the graph keeps it
33
+ coord escalate [--task ID] TEXT # a problem you cannot fix: the project manager asks the user
34
+ coord msg --from A [--task ID] [--fyi] TO TEXT # message a role or a worker; --task also notes the task
35
+ # --fyi: no run starts; the next run of TO reads it
36
+ coord broadcast --from A [--to workers|leads|all] TEXT
37
+ coord inbox [ROLE] [--wait] # read your messages
38
+ coord await # interactive Codex: arm the stop hook, then end your turn
39
+ coord goal list | goal show ID # open goals, or one goal and its tasks
40
+ coord who | status | log [N] # live workers, tasks by role, recent events
41
+ coord with-lock NAME -- CMD # run a command under a lock
42
+ ```
43
+
44
+ If a dispatcher serves your role, the prompt holds your messages. Do not run `coord inbox` then.
45
+
46
+ A worker has no inbox of its own. A message for a worker goes to the inbox of its role.
47
+ Any worker of the role can read it. The `for:` line names the worker.
48
+ If a message is about a task, send it with `--task ID`. The text then also stays as a note on the task.
49
+ If a message names a task that you do not hold, run `coord show ID` before you act.
50
+
51
+ ### Rules
52
+
53
+ 1. One writer per path. The task scope lists the paths that you own. Never edit outside the scope.
54
+ 2. A role with `can_edit: false` cannot commit. The git `pre-commit` hook refuses the commit.
55
+ 3. Run each local model generation under the `ollama` lock: `coord with-lock ollama -- <command>`.
56
+ 4. Run each command that needs a shared resource (browser, system tests, one fixed port) under one lock:
57
+ `coord with-lock system-test -- <command>`. Do not invent other lock names.
58
+ 5. Each worktree has its own test database and server port. Do not share a test database.
59
+
60
+ ### Tests
61
+
62
+ - Task tests: the unit tests and the tests for the changed behavior. The worker runs them before the report.
63
+ - Merge suite: the full suite, with system tests. Only the architect runs it, one time per goal.
64
+ - The reviewer does not run tests. The reviewer reads the TESTS line of the report.
65
+
66
+ ### Handoff artifacts
67
+
68
+ - A shared working file is an artifact. Write it to `$COORD_DIR/artifacts/<goal>/<name>.md`.
69
+ Run `mkdir -p` for the folder first.
70
+ - Never write an artifact inside a worktree. Worktrees do not share files.
71
+ - A worker commits each durable artifact (an approved spec, an ADR) on the goal branch.
72
+
73
+ ### Domain documentation
74
+
75
+ - `GLOSSARY.md` holds domain terms only. The file does not exist until the first term resolves.
76
+ - Each term has a bold name, one or two sentences, and an optional `_Avoid_` line for rejected words.
77
+ - The decisions folder holds the ADRs: `.agent/decisions/` if it exists, else `docs/decisions/`.
78
+ Append. Never rewrite an ADR.
79
+ - `graphify-out/obsidian/` is rebuilt from the code graph. Do not keep permanent notes there.
80
+ <!-- <<< multi-agent-flow <<< -->