zigrix 0.1.0-alpha.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.
- package/LICENSE +184 -0
- package/README.md +128 -0
- package/dist/agents/registry.d.ts +28 -0
- package/dist/agents/registry.js +98 -0
- package/dist/config/defaults.d.ts +66 -0
- package/dist/config/defaults.js +58 -0
- package/dist/config/load.d.ts +13 -0
- package/dist/config/load.js +96 -0
- package/dist/config/mutate.d.ts +10 -0
- package/dist/config/mutate.js +61 -0
- package/dist/config/schema.d.ts +132 -0
- package/dist/config/schema.js +123 -0
- package/dist/configure.d.ts +24 -0
- package/dist/configure.js +164 -0
- package/dist/doctor.d.ts +4 -0
- package/dist/doctor.js +99 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +791 -0
- package/dist/onboard.d.ts +99 -0
- package/dist/onboard.js +490 -0
- package/dist/orchestration/dispatch.d.ts +9 -0
- package/dist/orchestration/dispatch.js +146 -0
- package/dist/orchestration/evidence.d.ts +19 -0
- package/dist/orchestration/evidence.js +97 -0
- package/dist/orchestration/finalize.d.ts +7 -0
- package/dist/orchestration/finalize.js +136 -0
- package/dist/orchestration/pipeline.d.ts +11 -0
- package/dist/orchestration/pipeline.js +26 -0
- package/dist/orchestration/report.d.ts +5 -0
- package/dist/orchestration/report.js +92 -0
- package/dist/orchestration/worker.d.ts +34 -0
- package/dist/orchestration/worker.js +132 -0
- package/dist/rules/templates.d.ts +24 -0
- package/dist/rules/templates.js +73 -0
- package/dist/runner/run.d.ts +10 -0
- package/dist/runner/run.js +91 -0
- package/dist/runner/schema.d.ts +33 -0
- package/dist/runner/schema.js +10 -0
- package/dist/runner/store.d.ts +5 -0
- package/dist/runner/store.js +19 -0
- package/dist/state/events.d.ts +3 -0
- package/dist/state/events.js +53 -0
- package/dist/state/paths.d.ts +15 -0
- package/dist/state/paths.js +23 -0
- package/dist/state/tasks.d.ts +61 -0
- package/dist/state/tasks.js +247 -0
- package/dist/state/verify.d.ts +2 -0
- package/dist/state/verify.js +65 -0
- package/examples/hello-workflow.json +13 -0
- package/package.json +44 -0
- package/skills/zigrix-doctor/SKILL.md +20 -0
- package/skills/zigrix-evidence/SKILL.md +21 -0
- package/skills/zigrix-init/SKILL.md +23 -0
- package/skills/zigrix-report/SKILL.md +20 -0
- package/skills/zigrix-shared/SKILL.md +31 -0
- package/skills/zigrix-task-create/SKILL.md +34 -0
- package/skills/zigrix-task-status/SKILL.md +27 -0
- package/skills/zigrix-worker/SKILL.md +22 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { appendEvent, loadEvents, nowIso } from './events.js';
|
|
4
|
+
import { ensureBaseState } from './paths.js';
|
|
5
|
+
// ─── Paths ──────────────────────────────────────────────────────────────────
|
|
6
|
+
const TASK_ID_RE = /^(DEV|TEST|TASK)-(\d{8})-(\d{3})$/;
|
|
7
|
+
function metaPath(paths, taskId) {
|
|
8
|
+
return path.join(paths.tasksDir, `${taskId}.meta.json`);
|
|
9
|
+
}
|
|
10
|
+
function specPath(paths, taskId) {
|
|
11
|
+
return path.join(paths.tasksDir, `${taskId}.md`);
|
|
12
|
+
}
|
|
13
|
+
/** Legacy flat JSON path (backward compat read) */
|
|
14
|
+
function legacyPath(paths, taskId) {
|
|
15
|
+
return path.join(paths.tasksDir, `${taskId}.json`);
|
|
16
|
+
}
|
|
17
|
+
// ─── Read helpers ───────────────────────────────────────────────────────────
|
|
18
|
+
function readJson(filePath) {
|
|
19
|
+
try {
|
|
20
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
// ─── Task ID generation ─────────────────────────────────────────────────────
|
|
27
|
+
export function nextTaskId(paths, prefix = 'DEV') {
|
|
28
|
+
ensureBaseState(paths);
|
|
29
|
+
const today = nowIso().slice(0, 10).replaceAll('-', '');
|
|
30
|
+
const idPrefix = `${prefix}-${today}-`;
|
|
31
|
+
let maxN = 0;
|
|
32
|
+
for (const name of fs.readdirSync(paths.tasksDir)) {
|
|
33
|
+
const base = name.replace(/\.(meta\.json|json|md)$/, '');
|
|
34
|
+
const match = TASK_ID_RE.exec(base);
|
|
35
|
+
if (match && base.startsWith(idPrefix)) {
|
|
36
|
+
maxN = Math.max(maxN, Number(match[3]));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return `${idPrefix}${String(maxN + 1).padStart(3, '0')}`;
|
|
40
|
+
}
|
|
41
|
+
// ─── Spec template ──────────────────────────────────────────────────────────
|
|
42
|
+
function renderSpecMd(task) {
|
|
43
|
+
return [
|
|
44
|
+
'# Task Spec',
|
|
45
|
+
'',
|
|
46
|
+
'## 0) Task Metadata',
|
|
47
|
+
`- Task ID: \`${task.taskId}\``,
|
|
48
|
+
`- Title: ${task.title}`,
|
|
49
|
+
`- Scale: \`${task.scale}\``,
|
|
50
|
+
`- Status: \`${task.status}\``,
|
|
51
|
+
`- Created: ${task.createdAt}`,
|
|
52
|
+
task.requestedBy ? `- Requested by: ${task.requestedBy}` : null,
|
|
53
|
+
task.projectDir ? `- Project dir: ${task.projectDir}` : null,
|
|
54
|
+
`- Meta: \`${task.taskId}.meta.json\``,
|
|
55
|
+
'',
|
|
56
|
+
'## Spec Rule',
|
|
57
|
+
'- `normal|risky|large`: 이 문서 작성/갱신 완료 전 작업 진행 금지',
|
|
58
|
+
'- `simple`: 요약형 허용, 문서 파일은 반드시 생성',
|
|
59
|
+
'- 사람용 문서. 기계용 정보는 `.meta.json` 우선.',
|
|
60
|
+
'',
|
|
61
|
+
'## 1) Scope',
|
|
62
|
+
'### In-Scope',
|
|
63
|
+
task.description,
|
|
64
|
+
'',
|
|
65
|
+
'### Out-of-Scope',
|
|
66
|
+
'- (TBD)',
|
|
67
|
+
'',
|
|
68
|
+
'## 2) Orchestration Plan',
|
|
69
|
+
`- Required agents: ${task.requiredAgents.join(', ') || '(none)'}`,
|
|
70
|
+
task.selectedAgents?.length ? `- Selected agents: ${task.selectedAgents.join(', ')}` : null,
|
|
71
|
+
'',
|
|
72
|
+
'## 3) Notes',
|
|
73
|
+
'- (TBD)',
|
|
74
|
+
'',
|
|
75
|
+
].filter((line) => line !== null).join('\n');
|
|
76
|
+
}
|
|
77
|
+
// ─── Save / Load ────────────────────────────────────────────────────────────
|
|
78
|
+
export function saveTask(paths, task) {
|
|
79
|
+
ensureBaseState(paths);
|
|
80
|
+
task.updatedAt = nowIso();
|
|
81
|
+
// Write meta.json (machine data)
|
|
82
|
+
fs.writeFileSync(metaPath(paths, task.taskId), `${JSON.stringify(task, null, 2)}\n`, 'utf8');
|
|
83
|
+
// Write .md spec if it doesn't exist yet (don't overwrite human edits)
|
|
84
|
+
const mdPath = specPath(paths, task.taskId);
|
|
85
|
+
if (!fs.existsSync(mdPath)) {
|
|
86
|
+
fs.writeFileSync(mdPath, renderSpecMd(task), 'utf8');
|
|
87
|
+
}
|
|
88
|
+
rebuildIndex(paths);
|
|
89
|
+
return task;
|
|
90
|
+
}
|
|
91
|
+
export function loadTask(paths, taskId) {
|
|
92
|
+
// Prefer .meta.json, fall back to legacy .json
|
|
93
|
+
const meta = readJson(metaPath(paths, taskId));
|
|
94
|
+
if (meta)
|
|
95
|
+
return meta;
|
|
96
|
+
const legacy = readJson(legacyPath(paths, taskId));
|
|
97
|
+
return legacy;
|
|
98
|
+
}
|
|
99
|
+
export function listTasks(paths) {
|
|
100
|
+
ensureBaseState(paths);
|
|
101
|
+
const seen = new Set();
|
|
102
|
+
const tasks = [];
|
|
103
|
+
for (const name of fs.readdirSync(paths.tasksDir).sort()) {
|
|
104
|
+
let taskId = null;
|
|
105
|
+
if (name.endsWith('.meta.json')) {
|
|
106
|
+
taskId = name.replace(/\.meta\.json$/, '');
|
|
107
|
+
}
|
|
108
|
+
else if (name.endsWith('.json') && !name.endsWith('.meta.json')) {
|
|
109
|
+
taskId = name.replace(/\.json$/, '');
|
|
110
|
+
}
|
|
111
|
+
if (!taskId || seen.has(taskId))
|
|
112
|
+
continue;
|
|
113
|
+
if (!TASK_ID_RE.test(taskId))
|
|
114
|
+
continue;
|
|
115
|
+
const data = loadTask(paths, taskId);
|
|
116
|
+
if (data) {
|
|
117
|
+
seen.add(taskId);
|
|
118
|
+
tasks.push(data);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return tasks;
|
|
122
|
+
}
|
|
123
|
+
// ─── Events ─────────────────────────────────────────────────────────────────
|
|
124
|
+
export function listTaskEvents(paths, taskId) {
|
|
125
|
+
const rows = loadEvents(paths.eventsFile);
|
|
126
|
+
return taskId ? rows.filter((row) => String(row.taskId ?? '') === taskId) : rows;
|
|
127
|
+
}
|
|
128
|
+
// ─── Create ─────────────────────────────────────────────────────────────────
|
|
129
|
+
export function createTask(paths, params) {
|
|
130
|
+
const task = {
|
|
131
|
+
taskId: nextTaskId(paths, params.prefix ?? 'DEV'),
|
|
132
|
+
title: params.title,
|
|
133
|
+
description: params.description,
|
|
134
|
+
scale: params.scale ?? 'normal',
|
|
135
|
+
status: 'OPEN',
|
|
136
|
+
createdAt: nowIso(),
|
|
137
|
+
updatedAt: nowIso(),
|
|
138
|
+
requiredAgents: [...(params.requiredAgents ?? [])],
|
|
139
|
+
workerSessions: {},
|
|
140
|
+
...(params.projectDir ? { projectDir: params.projectDir } : {}),
|
|
141
|
+
...(params.requestedBy ? { requestedBy: params.requestedBy } : {}),
|
|
142
|
+
};
|
|
143
|
+
saveTask(paths, task);
|
|
144
|
+
appendEvent(paths.eventsFile, {
|
|
145
|
+
event: 'task_created',
|
|
146
|
+
taskId: task.taskId,
|
|
147
|
+
status: 'OPEN',
|
|
148
|
+
title: task.title,
|
|
149
|
+
scale: task.scale,
|
|
150
|
+
payload: { requiredAgents: task.requiredAgents, projectDir: params.projectDir ?? null },
|
|
151
|
+
});
|
|
152
|
+
rebuildIndex(paths);
|
|
153
|
+
return task;
|
|
154
|
+
}
|
|
155
|
+
// ─── Status transitions ─────────────────────────────────────────────────────
|
|
156
|
+
export function updateTaskStatus(paths, taskId, status) {
|
|
157
|
+
const task = loadTask(paths, taskId);
|
|
158
|
+
if (!task)
|
|
159
|
+
return null;
|
|
160
|
+
task.status = status;
|
|
161
|
+
saveTask(paths, task);
|
|
162
|
+
appendEvent(paths.eventsFile, { event: 'task_status_changed', taskId, status });
|
|
163
|
+
rebuildIndex(paths);
|
|
164
|
+
return task;
|
|
165
|
+
}
|
|
166
|
+
export function recordTaskProgress(paths, params) {
|
|
167
|
+
const task = loadTask(paths, params.taskId);
|
|
168
|
+
if (!task)
|
|
169
|
+
return null;
|
|
170
|
+
saveTask(paths, task);
|
|
171
|
+
const event = appendEvent(paths.eventsFile, {
|
|
172
|
+
event: 'progress_report',
|
|
173
|
+
taskId: params.taskId,
|
|
174
|
+
phase: 'execution',
|
|
175
|
+
actor: params.actor,
|
|
176
|
+
payload: {
|
|
177
|
+
message: params.message,
|
|
178
|
+
unitId: params.unitId,
|
|
179
|
+
workPackage: params.workPackage,
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
rebuildIndex(paths);
|
|
183
|
+
return event;
|
|
184
|
+
}
|
|
185
|
+
// ─── Stale policy ───────────────────────────────────────────────────────────
|
|
186
|
+
export function findStaleTasks(paths, hours = 24) {
|
|
187
|
+
const cutoff = Date.now() - hours * 3600 * 1000;
|
|
188
|
+
return listTasks(paths).filter((task) => task.status === 'IN_PROGRESS' && Date.parse(task.updatedAt) < cutoff);
|
|
189
|
+
}
|
|
190
|
+
export function applyStalePolicy(paths, hours = 24, reason = 'stale_timeout') {
|
|
191
|
+
const staleTasks = findStaleTasks(paths, hours);
|
|
192
|
+
const changed = staleTasks.map((task) => {
|
|
193
|
+
task.status = 'BLOCKED';
|
|
194
|
+
saveTask(paths, task);
|
|
195
|
+
const event = appendEvent(paths.eventsFile, {
|
|
196
|
+
event: 'task_blocked',
|
|
197
|
+
taskId: task.taskId,
|
|
198
|
+
phase: 'recovery',
|
|
199
|
+
actor: 'zigrix',
|
|
200
|
+
status: 'BLOCKED',
|
|
201
|
+
payload: { reason, previousStatus: 'IN_PROGRESS', hoursThreshold: hours },
|
|
202
|
+
});
|
|
203
|
+
return { taskId: task.taskId, event };
|
|
204
|
+
});
|
|
205
|
+
rebuildIndex(paths);
|
|
206
|
+
return { ok: true, hours, reason, count: changed.length, changed };
|
|
207
|
+
}
|
|
208
|
+
// ─── Index ──────────────────────────────────────────────────────────────────
|
|
209
|
+
export function rebuildIndex(paths) {
|
|
210
|
+
ensureBaseState(paths);
|
|
211
|
+
const tasks = listTasks(paths);
|
|
212
|
+
const events = loadEvents(paths.eventsFile);
|
|
213
|
+
const activeStatuses = new Set(['OPEN', 'IN_PROGRESS', 'BLOCKED', 'DONE_PENDING_REPORT']);
|
|
214
|
+
const statusBuckets = {};
|
|
215
|
+
const taskSummaries = {};
|
|
216
|
+
const activeTasks = {};
|
|
217
|
+
for (const task of tasks) {
|
|
218
|
+
statusBuckets[task.status] ??= [];
|
|
219
|
+
statusBuckets[task.status].push(task.taskId);
|
|
220
|
+
const summary = {
|
|
221
|
+
title: task.title,
|
|
222
|
+
status: task.status,
|
|
223
|
+
scale: task.scale,
|
|
224
|
+
requiredAgents: task.requiredAgents,
|
|
225
|
+
projectDir: task.projectDir ?? null,
|
|
226
|
+
updatedAt: task.updatedAt,
|
|
227
|
+
};
|
|
228
|
+
taskSummaries[task.taskId] = summary;
|
|
229
|
+
if (activeStatuses.has(task.status))
|
|
230
|
+
activeTasks[task.taskId] = summary;
|
|
231
|
+
}
|
|
232
|
+
const index = {
|
|
233
|
+
version: '2.0',
|
|
234
|
+
updatedAt: nowIso(),
|
|
235
|
+
policy: {
|
|
236
|
+
sourceOfTruth: 'tasks.jsonl',
|
|
237
|
+
projection: 'index.json',
|
|
238
|
+
qaRequiredForAllScales: true,
|
|
239
|
+
},
|
|
240
|
+
counts: { tasks: tasks.length, events: events.length },
|
|
241
|
+
statusBuckets,
|
|
242
|
+
activeTasks,
|
|
243
|
+
taskSummaries,
|
|
244
|
+
};
|
|
245
|
+
fs.writeFileSync(paths.indexFile, `${JSON.stringify(index, null, 2)}\n`, 'utf8');
|
|
246
|
+
return index;
|
|
247
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { listTasks } from './tasks.js';
|
|
4
|
+
function safeReadJson(filePath) {
|
|
5
|
+
try {
|
|
6
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function verifyTask(paths, task) {
|
|
13
|
+
const issues = [];
|
|
14
|
+
const evidenceDir = path.join(paths.evidenceDir, task.taskId);
|
|
15
|
+
const mergedPath = path.join(evidenceDir, '_merged.json');
|
|
16
|
+
const merged = safeReadJson(mergedPath);
|
|
17
|
+
const presentEvidenceAgents = fs.existsSync(evidenceDir)
|
|
18
|
+
? fs.readdirSync(evidenceDir).filter((name) => name.endsWith('.json') && name !== '_merged.json').map((name) => path.basename(name, '.json')).sort()
|
|
19
|
+
: [];
|
|
20
|
+
const requiredAgents = Array.isArray(task.requiredAgents) ? task.requiredAgents.map(String) : [];
|
|
21
|
+
const workerAgents = Object.keys(task.workerSessions ?? {}).sort();
|
|
22
|
+
for (const agentId of requiredAgents) {
|
|
23
|
+
if (!workerAgents.includes(agentId) && !presentEvidenceAgents.includes(agentId)) {
|
|
24
|
+
issues.push(`required agent '${agentId}' has neither worker session nor evidence`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if (merged) {
|
|
28
|
+
const mergedPresent = Array.isArray(merged.presentAgents) ? merged.presentAgents.map(String).sort() : [];
|
|
29
|
+
const mergedMissing = Array.isArray(merged.missingAgents) ? merged.missingAgents.map(String).sort() : [];
|
|
30
|
+
const computedMissing = requiredAgents.filter((agentId) => !presentEvidenceAgents.includes(agentId)).sort();
|
|
31
|
+
if (JSON.stringify(mergedPresent) !== JSON.stringify(presentEvidenceAgents)) {
|
|
32
|
+
issues.push('merged presentAgents does not match evidence files');
|
|
33
|
+
}
|
|
34
|
+
if (JSON.stringify(mergedMissing) !== JSON.stringify(computedMissing)) {
|
|
35
|
+
issues.push('merged missingAgents does not match requiredAgents/evidence files');
|
|
36
|
+
}
|
|
37
|
+
if (task.status === 'REPORTED' && merged.complete !== true) {
|
|
38
|
+
issues.push('task is REPORTED but merged evidence is incomplete');
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
else if (task.status === 'REPORTED') {
|
|
42
|
+
issues.push('task is REPORTED but merged evidence is missing');
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
taskId: task.taskId,
|
|
46
|
+
status: task.status,
|
|
47
|
+
requiredAgents,
|
|
48
|
+
workerAgents,
|
|
49
|
+
presentEvidenceAgents,
|
|
50
|
+
mergedExists: Boolean(merged),
|
|
51
|
+
ok: issues.length === 0,
|
|
52
|
+
issues,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
export function verifyState(paths) {
|
|
56
|
+
const tasks = listTasks(paths);
|
|
57
|
+
const checks = tasks.map((task) => verifyTask(paths, task));
|
|
58
|
+
const failures = checks.filter((item) => item.ok === false);
|
|
59
|
+
return {
|
|
60
|
+
ok: failures.length === 0,
|
|
61
|
+
taskCount: tasks.length,
|
|
62
|
+
failedCount: failures.length,
|
|
63
|
+
checks,
|
|
64
|
+
};
|
|
65
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "zigrix",
|
|
3
|
+
"version": "0.1.0-alpha.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Multi-project parallel task orchestration CLI for agent-assisted development",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"bin": {
|
|
8
|
+
"zigrix": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"skills",
|
|
13
|
+
"examples",
|
|
14
|
+
"README.md",
|
|
15
|
+
"LICENSE"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc -p tsconfig.json",
|
|
19
|
+
"clean": "rm -rf dist .zigrix",
|
|
20
|
+
"dev": "tsx src/index.ts",
|
|
21
|
+
"prebuild": "npm run clean",
|
|
22
|
+
"prepack": "npm run build",
|
|
23
|
+
"publish:check": "npm run build && npm run test && npm run smoke && bash scripts/release-smoke.sh && npm pack --dry-run && node dist/index.js state check --json",
|
|
24
|
+
"smoke": "node dist/index.js --version && node dist/index.js config validate --json",
|
|
25
|
+
"pretest": "npm run build",
|
|
26
|
+
"test": "vitest run",
|
|
27
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
28
|
+
},
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=22"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@inquirer/prompts": "^8.3.2",
|
|
34
|
+
"commander": "^14.0.0",
|
|
35
|
+
"yaml": "^2.8.1",
|
|
36
|
+
"zod": "^4.1.5"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@types/node": "^24.3.0",
|
|
40
|
+
"tsx": "^4.20.5",
|
|
41
|
+
"typescript": "^5.9.2",
|
|
42
|
+
"vitest": "^3.2.4"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: zigrix-doctor
|
|
3
|
+
version: 0.1.0
|
|
4
|
+
description: Inspect Zigrix environment readiness and OpenClaw integration prerequisites.
|
|
5
|
+
metadata:
|
|
6
|
+
openclaw:
|
|
7
|
+
requires:
|
|
8
|
+
bins: ["zigrix"]
|
|
9
|
+
cliHelp: "zigrix doctor --help"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# zigrix doctor
|
|
13
|
+
|
|
14
|
+
Run this before debugging install or integration issues.
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
zigrix doctor --json
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Returns Python, path, binary, and OpenClaw-home readiness details.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: zigrix-evidence
|
|
3
|
+
version: 0.2.0
|
|
4
|
+
description: Collect and merge task evidence in Zigrix.
|
|
5
|
+
metadata:
|
|
6
|
+
openclaw:
|
|
7
|
+
requires:
|
|
8
|
+
bins: ["zigrix"]
|
|
9
|
+
cliHelp: "zigrix evidence --help"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# zigrix evidence
|
|
13
|
+
|
|
14
|
+
Use evidence commands to persist verification outputs and merge completion state.
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
zigrix evidence collect --task-id DEV-20260316-001 --agent-id qa-zig --summary "QA passed" --json
|
|
18
|
+
zigrix evidence merge --task-id DEV-20260316-001 --require-qa --json
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Evidence files are stored under `~/.zigrix/evidence/<taskId>/`.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: zigrix-init
|
|
3
|
+
version: 0.2.0
|
|
4
|
+
description: "[DEPRECATED] Use zigrix onboard instead."
|
|
5
|
+
metadata:
|
|
6
|
+
openclaw:
|
|
7
|
+
requires:
|
|
8
|
+
bins: ["zigrix"]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Zigrix Init (Deprecated)
|
|
12
|
+
|
|
13
|
+
**Use `zigrix onboard` instead.**
|
|
14
|
+
|
|
15
|
+
`zigrix init` is a deprecated compatibility command. It creates a config file but does not perform PATH stabilization, skill registration, or agent import.
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# Preferred
|
|
19
|
+
zigrix onboard --yes --json
|
|
20
|
+
|
|
21
|
+
# Legacy (deprecated)
|
|
22
|
+
zigrix init --yes --json
|
|
23
|
+
```
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: zigrix-report
|
|
3
|
+
version: 0.1.0
|
|
4
|
+
description: Render a user-facing Zigrix completion report from merged evidence.
|
|
5
|
+
metadata:
|
|
6
|
+
openclaw:
|
|
7
|
+
requires:
|
|
8
|
+
bins: ["zigrix"]
|
|
9
|
+
cliHelp: "zigrix report --help"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# zigrix report
|
|
13
|
+
|
|
14
|
+
Render a user-facing completion summary after evidence merge.
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
zigrix report render --task-id TASK-20260313-001 --record-events --json
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
When `--record-events` is enabled, Zigrix appends `user_report_prepared` and `feedback_requested` events.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: zigrix-shared
|
|
3
|
+
version: 0.2.0
|
|
4
|
+
description: Shared guidance for Zigrix CLI usage, output modes, and safety.
|
|
5
|
+
metadata:
|
|
6
|
+
openclaw:
|
|
7
|
+
requires:
|
|
8
|
+
bins: ["zigrix"]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Zigrix Shared Reference
|
|
12
|
+
|
|
13
|
+
Use Zigrix for multi-project parallel task orchestration with file-backed, inspectable state.
|
|
14
|
+
|
|
15
|
+
## Rules
|
|
16
|
+
- Prefer `--json` for automation-heavy flows.
|
|
17
|
+
- Global state lives in `~/.zigrix/` (override: `ZIGRIX_HOME` env).
|
|
18
|
+
- Tasks are NOT project-bound — one Zigrix instance manages tasks across projects.
|
|
19
|
+
- Do not assume OpenClaw internals are required unless the task explicitly needs them.
|
|
20
|
+
|
|
21
|
+
## Common commands
|
|
22
|
+
```bash
|
|
23
|
+
zigrix doctor --json
|
|
24
|
+
zigrix task list --json
|
|
25
|
+
zigrix task dispatch --title "..." --description "..." --scale normal --json
|
|
26
|
+
zigrix task finalize <taskId> --auto-report --json
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Safety
|
|
30
|
+
- Confirm before destructive actions.
|
|
31
|
+
- Treat runtime state and source code as separate concerns.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: zigrix-task-create
|
|
3
|
+
version: 0.2.0
|
|
4
|
+
description: Create a new Zigrix task with title, description, and scale.
|
|
5
|
+
metadata:
|
|
6
|
+
openclaw:
|
|
7
|
+
requires:
|
|
8
|
+
bins: ["zigrix"]
|
|
9
|
+
cliHelp: "zigrix task create --help"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# zigrix task create
|
|
13
|
+
|
|
14
|
+
Create a task in `~/.zigrix/tasks/`.
|
|
15
|
+
|
|
16
|
+
For full orchestration metadata (work packages, execution units, boot prompt), use `zigrix task dispatch` instead.
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# Low-level task creation
|
|
20
|
+
zigrix task create \
|
|
21
|
+
--title "Implement installer" \
|
|
22
|
+
--description "Create a safe app-owned venv installer" \
|
|
23
|
+
--scale normal \
|
|
24
|
+
--json
|
|
25
|
+
|
|
26
|
+
# Full orchestration dispatch (preferred for agent workflows)
|
|
27
|
+
zigrix task dispatch \
|
|
28
|
+
--title "Implement installer" \
|
|
29
|
+
--description "Create a safe app-owned venv installer" \
|
|
30
|
+
--scale normal \
|
|
31
|
+
--json
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Prefer `--json` when another agent or script will consume the result.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: zigrix-task-status
|
|
3
|
+
version: 0.1.0
|
|
4
|
+
description: Inspect Zigrix task records and state transitions.
|
|
5
|
+
metadata:
|
|
6
|
+
openclaw:
|
|
7
|
+
requires:
|
|
8
|
+
bins: ["zigrix"]
|
|
9
|
+
cliHelp: "zigrix task status --help"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# zigrix task status
|
|
13
|
+
|
|
14
|
+
Use this to inspect one task or list tasks.
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
zigrix task list --json
|
|
18
|
+
zigrix task status TASK-20260313-001 --json
|
|
19
|
+
zigrix task events TASK-20260313-001 --json
|
|
20
|
+
zigrix task progress --task-id TASK-20260313-001 --actor pro-zig --message "진행 상황 요약" --json
|
|
21
|
+
zigrix task stale --hours 24 --json
|
|
22
|
+
zigrix task start TASK-20260313-001
|
|
23
|
+
zigrix task finalize TASK-20260313-001
|
|
24
|
+
zigrix task report TASK-20260313-001
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Treat status transitions as explicit lifecycle events.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: zigrix-worker
|
|
3
|
+
version: 0.2.0
|
|
4
|
+
description: Prepare, register, and complete Zigrix worker runs.
|
|
5
|
+
metadata:
|
|
6
|
+
openclaw:
|
|
7
|
+
requires:
|
|
8
|
+
bins: ["zigrix"]
|
|
9
|
+
cliHelp: "zigrix worker --help"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# zigrix worker
|
|
13
|
+
|
|
14
|
+
Use worker lifecycle commands to bridge agent execution and global orchestration state.
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
zigrix worker prepare --task-id DEV-20260316-001 --agent-id qa-zig --description "Run QA checks" --json
|
|
18
|
+
zigrix worker register --task-id DEV-20260316-001 --agent-id qa-zig --session-key agent:test:qa --run-id run-001 --json
|
|
19
|
+
zigrix worker complete --task-id DEV-20260316-001 --agent-id qa-zig --session-key agent:test:qa --run-id run-001 --json
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
These commands intentionally avoid hard-coding OpenClaw internals into the Zigrix core.
|