@mestreyoda/fabrica 0.2.9 → 0.2.12
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.
- package/ARCHITECTURE.md +12 -6
- package/CHANGELOG.md +17 -0
- package/README.md +88 -30
- package/defaults/fabrica/prompts/architect.md +6 -6
- package/defaults/fabrica/prompts/reviewer.md +3 -3
- package/defaults/fabrica/prompts/tester.md +8 -7
- package/dist/index.js +5420 -1210
- package/openclaw.plugin.json +73 -0
- package/package.json +14 -5
- package/dist/index.js.map +0 -7
package/ARCHITECTURE.md
CHANGED
|
@@ -63,17 +63,23 @@ Important invariants:
|
|
|
63
63
|
|
|
64
64
|
## Installation model
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
Fabrica is distributed as a self-contained OpenClaw plugin package.
|
|
67
|
+
|
|
68
|
+
The supported operator path is:
|
|
67
69
|
|
|
68
70
|
```bash
|
|
69
|
-
openclaw plugins install
|
|
71
|
+
openclaw plugins install @mestreyoda/fabrica
|
|
70
72
|
```
|
|
71
73
|
|
|
72
|
-
|
|
74
|
+
The installed extension must be loadable in isolation. Fabrica may depend on
|
|
75
|
+
OpenClaw only through the plugin host ABI and runtime objects passed by the
|
|
76
|
+
host. It must not require manual symlinks, local `npm install`, or host-global
|
|
77
|
+
module resolution to load.
|
|
73
78
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
79
|
+
External credentials and routes such as GitHub auth, Telegram chat IDs, and
|
|
80
|
+
webhook secrets are operational configuration, not installation dependencies.
|
|
81
|
+
Fabrica's `doctor` and `setup` flows guide and validate that operational
|
|
82
|
+
configuration where applicable.
|
|
77
83
|
|
|
78
84
|
## Operational notes
|
|
79
85
|
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.2.12 - 2026-03-31
|
|
4
|
+
|
|
5
|
+
- Made the published plugin self-contained by replacing remaining runtime helper imports from `openclaw/plugin-sdk`.
|
|
6
|
+
- Added release gates for runtime-boundary and isolated installability verification, with fail-closed behavior, timeouts, and cleanup.
|
|
7
|
+
- Documented the real install contract and workspace-scoped operational setup flow in the package README and architecture notes.
|
|
8
|
+
- Aligned local deploy to the same contract by removing the extension `node_modules` symlink fallback.
|
|
9
|
+
|
|
10
|
+
## 0.2.11 - 2026-03-31
|
|
11
|
+
|
|
12
|
+
- Unified reviewer completion around the canonical `Review result: APPROVE|REJECT` contract.
|
|
13
|
+
- Hardened dispatch identity and reduced heartbeat progression to repair-oriented behavior.
|
|
14
|
+
- Enforced canonical PR selection across reviewer/tester and queue-side flows.
|
|
15
|
+
- Preserved and hardened the Telegram three-plane model: DM bootstrap, project forum topics, and ops routing.
|
|
16
|
+
- Restored confidence lanes for release verification with explicit `test:unit`, `test:e2e`, and `test:hot-path`.
|
|
17
|
+
- Aligned plugin config governance and observability surfaces so runtime knobs are real and misleading signals no longer present themselves as authoritative.
|
package/README.md
CHANGED
|
@@ -64,6 +64,9 @@ The heartbeat ticks every 60 seconds. On each tick, Fabrica alternates between a
|
|
|
64
64
|
openclaw plugins install @mestreyoda/fabrica
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
+
That install should be enough for OpenClaw to load Fabrica immediately, without
|
|
68
|
+
manual remediation.
|
|
69
|
+
|
|
67
70
|
### Via GitHub clone
|
|
68
71
|
|
|
69
72
|
```bash
|
|
@@ -74,37 +77,53 @@ openclaw plugins install -l ~/fabrica
|
|
|
74
77
|
After installation, verify the plugin loaded correctly:
|
|
75
78
|
|
|
76
79
|
```bash
|
|
77
|
-
openclaw plugins
|
|
78
|
-
openclaw fabrica doctor
|
|
80
|
+
openclaw plugins inspect fabrica
|
|
79
81
|
```
|
|
80
82
|
|
|
83
|
+
## Loadability vs operational readiness
|
|
84
|
+
|
|
85
|
+
- **Loadable:** the plugin installs and OpenClaw can load it immediately.
|
|
86
|
+
- **Operational:** Fabrica has the GitHub, Telegram, and optional webhook
|
|
87
|
+
configuration needed for your workflow.
|
|
88
|
+
|
|
89
|
+
`openclaw plugins inspect fabrica` is the loadability check after install.
|
|
90
|
+
`openclaw fabrica doctor` runs once the plugin is loaded and checks the
|
|
91
|
+
operational/workspace state, then tells you what is still missing.
|
|
92
|
+
|
|
81
93
|
## Quick start
|
|
82
94
|
|
|
83
|
-
**1.
|
|
95
|
+
**1. Install Fabrica**:
|
|
84
96
|
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
```bash
|
|
98
|
+
openclaw plugins install @mestreyoda/fabrica
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The plugin should load immediately after install, without manual remediation.
|
|
102
|
+
|
|
103
|
+
**2. Confirm loadability**:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
openclaw plugins inspect fabrica
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**3. Configure operational state for a workspace**:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
openclaw fabrica doctor workspace --workspace /path/to/workspace
|
|
113
|
+
openclaw fabrica setup --workspace /path/to/workspace --new-agent fabrica
|
|
99
114
|
```
|
|
100
115
|
|
|
101
|
-
|
|
116
|
+
Use `openclaw fabrica setup --agent <id>` if you already have an agent. GitHub,
|
|
117
|
+
Telegram, and webhook behavior are separate operational concerns, not
|
|
118
|
+
installation dependencies.
|
|
119
|
+
|
|
120
|
+
**4. Restart the gateway**:
|
|
102
121
|
|
|
103
122
|
```bash
|
|
104
123
|
systemctl --user restart openclaw-gateway.service
|
|
105
124
|
```
|
|
106
125
|
|
|
107
|
-
**
|
|
126
|
+
**5. Trigger a new project programmatically**:
|
|
108
127
|
|
|
109
128
|
```bash
|
|
110
129
|
cd ~/fabrica # GitHub clone install only
|
|
@@ -116,13 +135,13 @@ npx tsx scripts/genesis-trigger.ts "A CLI tool that counts words in a file" \
|
|
|
116
135
|
|
|
117
136
|
Remove `--dry-run` to execute for real.
|
|
118
137
|
|
|
119
|
-
**
|
|
138
|
+
**6. Watch the pipeline run**:
|
|
120
139
|
|
|
121
140
|
```bash
|
|
122
141
|
tail -f ~/.openclaw/workspace/logs/genesis.log
|
|
123
142
|
```
|
|
124
143
|
|
|
125
|
-
**
|
|
144
|
+
**7. Check metrics**:
|
|
126
145
|
|
|
127
146
|
```bash
|
|
128
147
|
openclaw fabrica metrics
|
|
@@ -132,7 +151,7 @@ openclaw fabrica metrics
|
|
|
132
151
|
|
|
133
152
|
### Minimal (gh CLI only)
|
|
134
153
|
|
|
135
|
-
This
|
|
154
|
+
This mode uses authenticated `gh` CLI for all GitHub operations. Worker models, levels, and workflow routing live in the project workflow files, not in `openclaw.json`.
|
|
136
155
|
|
|
137
156
|
```json
|
|
138
157
|
{
|
|
@@ -140,13 +159,49 @@ This configuration uses `gh` CLI for all GitHub operations (no GitHub App needed
|
|
|
140
159
|
"entries": {
|
|
141
160
|
"fabrica": {
|
|
142
161
|
"config": {
|
|
143
|
-
"
|
|
144
|
-
"
|
|
162
|
+
"work_heartbeat": {
|
|
163
|
+
"enabled": true,
|
|
164
|
+
"intervalSeconds": 60,
|
|
165
|
+
"maxPickupsPerTick": 4
|
|
145
166
|
},
|
|
146
|
-
"
|
|
147
|
-
|
|
148
|
-
"
|
|
149
|
-
"
|
|
167
|
+
"projectExecution": "parallel",
|
|
168
|
+
"notifications": {
|
|
169
|
+
"workerStart": true,
|
|
170
|
+
"workerComplete": true
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Optional GitHub App/webhook settings also live under `plugins.entries.fabrica.config.providers.github`.
|
|
180
|
+
|
|
181
|
+
### With GitHub App / webhook config
|
|
182
|
+
|
|
183
|
+
Use plugin config when you want explicit webhook behavior or provider auth profiles:
|
|
184
|
+
|
|
185
|
+
```json
|
|
186
|
+
{
|
|
187
|
+
"plugins": {
|
|
188
|
+
"entries": {
|
|
189
|
+
"fabrica": {
|
|
190
|
+
"config": {
|
|
191
|
+
"providers": {
|
|
192
|
+
"github": {
|
|
193
|
+
"defaultAuthProfile": "app",
|
|
194
|
+
"webhookMode": "optional",
|
|
195
|
+
"webhookPath": "/plugins/fabrica/github/webhook",
|
|
196
|
+
"webhookSecretEnv": "FABRICA_GITHUB_WEBHOOK_SECRET",
|
|
197
|
+
"authProfiles": {
|
|
198
|
+
"app": {
|
|
199
|
+
"mode": "github-app",
|
|
200
|
+
"appIdEnv": "FABRICA_GITHUB_APP_ID",
|
|
201
|
+
"privateKeyPathEnv": "FABRICA_GITHUB_APP_KEY_PATH"
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
150
205
|
}
|
|
151
206
|
}
|
|
152
207
|
}
|
|
@@ -157,7 +212,7 @@ This configuration uses `gh` CLI for all GitHub operations (no GitHub App needed
|
|
|
157
212
|
|
|
158
213
|
### With Telegram
|
|
159
214
|
|
|
160
|
-
Telegram enables DM-based project bootstrap
|
|
215
|
+
Telegram enables DM-based project bootstrap, per-project forum topics, and a separate ops chat for heartbeat and cron notifications.
|
|
161
216
|
|
|
162
217
|
```json
|
|
163
218
|
{
|
|
@@ -177,6 +232,7 @@ Telegram enables DM-based project bootstrap and per-project forum topic notifica
|
|
|
177
232
|
"telegram": {
|
|
178
233
|
"bootstrapDmEnabled": true,
|
|
179
234
|
"projectsForumChatId": "<YOUR_PROJECTS_FORUM_CHAT_ID>",
|
|
235
|
+
"projectsForumAccountId": "<OPTIONAL_TELEGRAM_ACCOUNT_ID>",
|
|
180
236
|
"opsChatId": "<YOUR_OPS_CHAT_ID>"
|
|
181
237
|
}
|
|
182
238
|
}
|
|
@@ -186,7 +242,7 @@ Telegram enables DM-based project bootstrap and per-project forum topic notifica
|
|
|
186
242
|
}
|
|
187
243
|
```
|
|
188
244
|
|
|
189
|
-
With Telegram enabled, send a project idea to the bot in a DM. Fabrica will ask clarifying questions, provision the GitHub repo,
|
|
245
|
+
With Telegram enabled, send a project idea to the bot in a DM. Fabrica will ask clarifying questions, provision the GitHub repo, create a dedicated forum topic for the project, and keep ops-only notifications on the separate `opsChatId` route.
|
|
190
246
|
|
|
191
247
|
## Programmatic genesis
|
|
192
248
|
|
|
@@ -227,6 +283,8 @@ Run tests:
|
|
|
227
283
|
|
|
228
284
|
```bash
|
|
229
285
|
npm test
|
|
286
|
+
npm run test:all
|
|
287
|
+
npm run test:hot-path
|
|
230
288
|
```
|
|
231
289
|
|
|
232
290
|
Build:
|
|
@@ -96,7 +96,7 @@ Brief summary of what needs to be implemented and why.
|
|
|
96
96
|
### How to Create
|
|
97
97
|
|
|
98
98
|
1. Call `task_create` with:
|
|
99
|
-
- `projectSlug`:
|
|
99
|
+
- `projectSlug`: the value from the `Channel:` line in your task message (`task_create` still expects this field name)
|
|
100
100
|
- `title`: clear, actionable title (e.g. "Implement SQLite session persistence")
|
|
101
101
|
- `description`: use the format above — detailed enough for a developer to start immediately
|
|
102
102
|
|
|
@@ -105,13 +105,13 @@ Brief summary of what needs to be implemented and why.
|
|
|
105
105
|
|
|
106
106
|
**Example:**
|
|
107
107
|
```
|
|
108
|
-
task_create({ projectSlug: "
|
|
108
|
+
task_create({ projectSlug: "<project slug from the 'Channel:' line in the task message>", title: "Implement SQLite session persistence", description: "From research #42\n\n## Overview\nReplace in-memory Map with SQLite...\n\n## Implementation Checklist\n\n### Phase 1: Schema & Migration (~1 day)\n- [ ] Create sessions table schema in db/schema.sql\n- [ ] Add migration logic in db/migrate.ts\n..." })
|
|
109
109
|
// → returns issue id: 43, url: "https://github.com/.../43"
|
|
110
110
|
|
|
111
111
|
work_finish({
|
|
112
112
|
role: "architect",
|
|
113
113
|
result: "done",
|
|
114
|
-
|
|
114
|
+
channelId: "my-app",
|
|
115
115
|
summary: "Recommended SQLite approach. Created task #43.",
|
|
116
116
|
createdTasks: [
|
|
117
117
|
{ id: 43, title: "Implement SQLite session persistence", url: "https://github.com/.../43" }
|
|
@@ -136,10 +136,10 @@ The task is created in Planning state — the operator reviews and moves it to t
|
|
|
136
136
|
|
|
137
137
|
When you are done, **call `work_finish` yourself** — do not just announce in text.
|
|
138
138
|
|
|
139
|
-
- **Done:** `work_finish({ role: "architect", result: "done",
|
|
140
|
-
- **Blocked:** `work_finish({ role: "architect", result: "blocked",
|
|
139
|
+
- **Done:** `work_finish({ role: "architect", result: "done", channelId: "<project slug from the 'Channel:' line in the task message>", summary: "<recommendation + created task numbers>", createdTasks: [{ id, title, url }] })`
|
|
140
|
+
- **Blocked:** `work_finish({ role: "architect", result: "blocked", channelId: "<project slug from the 'Channel:' line in the task message>", summary: "<what you need>" })`
|
|
141
141
|
|
|
142
|
-
The
|
|
142
|
+
The project slug is included on the `Channel:` line in your task message. Your session is persistent — you may be called back for refinements.
|
|
143
143
|
|
|
144
144
|
## Tools You Should NOT Use
|
|
145
145
|
|
|
@@ -73,7 +73,7 @@ Do **not** treat the task envelope (`Repo:`, `Project:`, `Channel:`, branch hint
|
|
|
73
73
|
|
|
74
74
|
- Read the PR diff carefully
|
|
75
75
|
- Check the code against the review checklist
|
|
76
|
-
-
|
|
76
|
+
- Output your decision in the format described in **Completing Your Task** below
|
|
77
77
|
|
|
78
78
|
## Conventions
|
|
79
79
|
|
|
@@ -85,9 +85,9 @@ Do **not** treat the task envelope (`Repo:`, `Project:`, `Channel:`, branch hint
|
|
|
85
85
|
|
|
86
86
|
## Filing Follow-Up Issues
|
|
87
87
|
|
|
88
|
-
If you discover unrelated bugs or needed improvements, call `task_create
|
|
88
|
+
If you discover unrelated bugs or needed improvements, call `task_create` with the project slug from the `Channel:` line in your task message:
|
|
89
89
|
|
|
90
|
-
`task_create({ projectSlug: "<from task message>", title: "Bug: ...", description: "..." })`
|
|
90
|
+
`task_create({ projectSlug: "<project slug from the 'Channel:' line in the task message>", title: "Bug: ...", description: "..." })`
|
|
91
91
|
|
|
92
92
|
## Completing Your Task
|
|
93
93
|
|
|
@@ -124,13 +124,14 @@ Use `task_comment` to post your findings in this format:
|
|
|
124
124
|
|
|
125
125
|
### 6. Call work_finish
|
|
126
126
|
|
|
127
|
-
- **Pass:** `work_finish({ role: "tester", result: "pass", channelId: "<project slug from '
|
|
128
|
-
- **Fail:** `work_finish({ role: "tester", result: "fail", channelId: "<project slug from '
|
|
129
|
-
- **
|
|
130
|
-
- **
|
|
127
|
+
- **Pass:** `work_finish({ role: "tester", result: "pass", channelId: "<project slug from the 'Channel:' line in the task message>", summary: "<brief summary>" })`
|
|
128
|
+
- **Fail:** `work_finish({ role: "tester", result: "fail", channelId: "<project slug from the 'Channel:' line in the task message>", summary: "<specific failures>" })`
|
|
129
|
+
- **Fail Infra:** `work_finish({ role: "tester", result: "fail_infra", channelId: "<project slug from the 'Channel:' line in the task message>", summary: "<toolchain or environment failure that prevented QA>" })`
|
|
130
|
+
- **Refine:** `work_finish({ role: "tester", result: "refine", channelId: "<project slug from the 'Channel:' line in the task message>", summary: "<what needs human input>" })`
|
|
131
|
+
- **Blocked:** `work_finish({ role: "tester", result: "blocked", channelId: "<project slug from the 'Channel:' line in the task message>", summary: "<what you need>" })`
|
|
131
132
|
|
|
132
133
|
> **IMPORTANT:** The `channelId` parameter accepts the project slug (e.g., "gestao-notas").
|
|
133
|
-
> Extract it from the "
|
|
134
|
+
> Extract it from the "Channel: <slug>" line in your task message. Do NOT use the numeric
|
|
134
135
|
> channel ID — use the project slug to avoid resolution errors when channels are shared.
|
|
135
136
|
|
|
136
137
|
## Conventions
|
|
@@ -140,9 +141,9 @@ Use `task_comment` to post your findings in this format:
|
|
|
140
141
|
|
|
141
142
|
## Filing Follow-Up Issues
|
|
142
143
|
|
|
143
|
-
If you discover unrelated bugs or needed improvements during your work, call `task_create
|
|
144
|
+
If you discover unrelated bugs or needed improvements during your work, call `task_create` with the project slug from the `Channel:` line in your task message:
|
|
144
145
|
|
|
145
|
-
`task_create({ projectSlug: "<from task message>", title: "Bug: ...", description: "..." })`
|
|
146
|
+
`task_create({ projectSlug: "<project slug from the 'Channel:' line in the task message>", title: "Bug: ...", description: "..." })`
|
|
146
147
|
|
|
147
148
|
## Tools You Should NOT Use
|
|
148
149
|
|