@crewx/wi 0.1.10-rc.19 → 0.1.10-rc.191
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/SKILL.md +121 -48
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +8 -105
- package/package.json +14 -2
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
package/SKILL.md
CHANGED
|
@@ -11,6 +11,23 @@ metadata:
|
|
|
11
11
|
> **Core principle**: Context belongs in the file, not in your head.
|
|
12
12
|
> An agent should be able to execute a WI without asking questions.
|
|
13
13
|
|
|
14
|
+
## Command support
|
|
15
|
+
|
|
16
|
+
The dispatch logic in `packages/built-in/wi/cli.ts` is the source of truth for this table.
|
|
17
|
+
|
|
18
|
+
| Route | Status | Notes |
|
|
19
|
+
|--------|--------|-------|
|
|
20
|
+
| `usage` | Implemented | Shows this guide. |
|
|
21
|
+
| `create-batch` | Implemented | Creates gated draft WIs from batch JSON. |
|
|
22
|
+
| `board tick` | Implemented | Advances one approved board WI when gates pass. |
|
|
23
|
+
| `board digest` | Implemented | Sends and prints the overnight board summary. |
|
|
24
|
+
| `draft` | Planned / not implemented | Manual procedure below; not a runnable CLI route. |
|
|
25
|
+
| `issue` | Planned / not implemented | Manual procedure below; not a runnable CLI route. |
|
|
26
|
+
| `list` | Planned / not implemented | Manual procedure below; not a runnable CLI route. |
|
|
27
|
+
| `review` | Planned / not implemented | Manual procedure below; not a runnable CLI route. |
|
|
28
|
+
|
|
29
|
+
The four planned routes currently print `'<command>' is not yet implemented.` and return exit code `0`. Do not treat that exit code as proof that the requested operation succeeded.
|
|
30
|
+
|
|
14
31
|
## When to use
|
|
15
32
|
|
|
16
33
|
- When delegating work to an agent
|
|
@@ -21,17 +38,80 @@ metadata:
|
|
|
21
38
|
|
|
22
39
|
---
|
|
23
40
|
|
|
24
|
-
##
|
|
41
|
+
## Implemented commands
|
|
25
42
|
|
|
26
|
-
###
|
|
43
|
+
### create-batch — Materialize a gated WI plan
|
|
27
44
|
|
|
28
|
-
|
|
29
|
-
|
|
45
|
+
Creates multiple draft WIs in one atomic batch. Use this after a plan approval gate, not while brainstorming.
|
|
46
|
+
|
|
47
|
+
Input is JSON from `--file` or stdin:
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"board": "brd_release",
|
|
52
|
+
"source": "manual",
|
|
53
|
+
"items": [
|
|
54
|
+
{
|
|
55
|
+
"title": "Implement SDK contract",
|
|
56
|
+
"assignee": "core_dev",
|
|
57
|
+
"depends_on": [],
|
|
58
|
+
"body": "Full WI body markdown"
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
crewx wi create-batch --file .crewx/plan.json
|
|
66
|
+
cat .crewx/plan.json | crewx wi create-batch
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Output:
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{ "created": [{ "wi_id": "WI-20260730-001", "title": "Implement SDK contract" }] }
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
All created WIs start as `draft` and include `board`, `source` (default `manual`), and `depends_on` frontmatter. ID allocation is locked across processes.
|
|
76
|
+
|
|
77
|
+
### board tick / digest — Goal-board automatic chain
|
|
78
|
+
|
|
79
|
+
`tick` advances at most one WI from a board batch, after conservative gates:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
crewx wi board tick brd_release --json
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Cron registration must use command mode and a literal board id. Do not interpolate a
|
|
86
|
+
board name, WI title, or other free text into the scheduled command string.
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
crewx cron add "0 * * * *" "crewx wi board tick brd_release --json" --mode command --name "Goal board tick"
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Tick behavior:
|
|
93
|
+
|
|
94
|
+
- Uses `.crewx/boards/<brd-id>/state.json` under a board file lock.
|
|
95
|
+
- Checks subscription usage limits through the CrewX server; if unavailable, skips the tick and increments `skippedTicks`.
|
|
96
|
+
- Runs only one workflow at a time.
|
|
97
|
+
- Never auto-approves `approval` nodes. Human-gated runs are marked `human_wait`.
|
|
98
|
+
- Stops the chain after three consecutive failures and sends a notification.
|
|
99
|
+
|
|
100
|
+
`digest` sends the overnight summary notification and includes `metadata.boardId`:
|
|
30
101
|
|
|
31
102
|
```bash
|
|
32
|
-
|
|
103
|
+
crewx wi board digest brd_release --json
|
|
33
104
|
```
|
|
34
105
|
|
|
106
|
+
## Manual procedures
|
|
107
|
+
|
|
108
|
+
### Manual procedure: draft — Create a draft
|
|
109
|
+
|
|
110
|
+
There is no implemented CLI route for `draft`; follow this procedure manually.
|
|
111
|
+
|
|
112
|
+
Takes the user's intent and drafts a Work Instruction.
|
|
113
|
+
The lead reads the design doc and fills in the details.
|
|
114
|
+
|
|
35
115
|
**Lead execution steps:**
|
|
36
116
|
|
|
37
117
|
1. Check today's date + existing WI count → assign ID
|
|
@@ -41,20 +121,20 @@ npx crewx skill wi draft "task description"
|
|
|
41
121
|
|
|
42
122
|
2. Read relevant section from design doc
|
|
43
123
|
```bash
|
|
44
|
-
|
|
124
|
+
crewx doc section docs/design.md "section name"
|
|
45
125
|
```
|
|
46
126
|
|
|
47
127
|
3. Identify affected files + **impact analysis**
|
|
48
128
|
```bash
|
|
49
129
|
# Track symbol references
|
|
50
|
-
|
|
51
|
-
|
|
130
|
+
crewx skill tsserver find "symbolName"
|
|
131
|
+
crewx skill tsserver references path/to/file.ts lineNumber columnNumber
|
|
52
132
|
|
|
53
133
|
# If API changed, find consumers
|
|
54
|
-
|
|
134
|
+
crewx search "endpointName" ./src/ui --glob="**/*.ts,**/*.tsx"
|
|
55
135
|
|
|
56
136
|
# If types changed, find usages
|
|
57
|
-
|
|
137
|
+
crewx search "typeName" ./src --glob="**/*.ts,**/*.tsx"
|
|
58
138
|
```
|
|
59
139
|
|
|
60
140
|
→ Fill in `api_changed`, `schema_changed`, `consumers`, `risk_level`
|
|
@@ -80,39 +160,40 @@ npx crewx skill wi draft "task description"
|
|
|
80
160
|
|
|
81
161
|
---
|
|
82
162
|
|
|
83
|
-
### issue — Issue to an agent
|
|
163
|
+
### Manual procedure: issue — Issue to an agent
|
|
84
164
|
|
|
85
|
-
|
|
165
|
+
There is no implemented CLI route for `issue`; use the procedure below to issue an approved Work Instruction.
|
|
86
166
|
|
|
87
|
-
|
|
88
|
-
npx crewx skill wi issue WI-20260312-001
|
|
89
|
-
```
|
|
167
|
+
Deliver an approved Work Instruction to the assigned agent.
|
|
90
168
|
|
|
91
169
|
**Issue steps:**
|
|
92
170
|
|
|
93
|
-
1. Read WI file
|
|
171
|
+
1. Read the WI file, confirm its status is `approved`, and identify its `impl_agent` before dispatching. (`consultant` is for advisory work, not an issue target.)
|
|
94
172
|
|
|
95
|
-
2. Check
|
|
96
|
-
|
|
97
|
-
3. Check agent memory (any in-progress work?)
|
|
173
|
+
2. Check agent memory (any in-progress work?)
|
|
98
174
|
```bash
|
|
99
|
-
|
|
175
|
+
crewx memory index {impl_agent}
|
|
100
176
|
```
|
|
101
177
|
|
|
102
|
-
|
|
178
|
+
3. Set the recipient with `--to` and send the complete WI as the body. Put a long WI in a file; its path and first line never select the recipient.
|
|
103
179
|
```bash
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
180
|
+
crewx x --to {impl_agent} -f wi-body.md --thread="WI-{ID}" --out=".crewx/result/WI-{ID}-impl.txt"
|
|
181
|
+
```
|
|
182
|
+
`wi-body.md` must contain the complete Work Instruction text. A bare file path as the whole prompt is insufficient.
|
|
183
|
+
The file supplies only the body; the recipient is specified by `--to`.
|
|
108
184
|
|
|
109
|
-
|
|
110
|
-
|
|
185
|
+
For `crewx x`, `--wait` requests synchronous execution; this differs from the `--wait=N` polling limit used by `crewx result` in the next step.
|
|
186
|
+
4. In agent context, the immediate task ID returned by `crewx x` is a receipt, not completion. Recover the terminal result from the foreground with:
|
|
187
|
+
```bash
|
|
188
|
+
crewx result <task-id> --wait=N
|
|
111
189
|
```
|
|
190
|
+
Use `N <= 300`. Exit `124` means the task is still running, so repeat the result command using the next advised wait. Read both the terminal state (`success`, `failed`, or `stopped`) and the result body before deciding what happened; `failed` with reason `runner_lost` means the end of the run was not observed and it may still be running.
|
|
191
|
+
|
|
192
|
+
If `--out` is used in receipt mode, the output file is written when the task completes, not when the receipt is returned. Do not wrap delegation with `timeout`, `&`, `nohup`, or any other background-process ownership mechanism.
|
|
112
193
|
|
|
113
|
-
5.
|
|
194
|
+
5. After dispatch, update WI status → `in-progress`. Only after the terminal result is available and the ACs are verified may the WI be marked `done`.
|
|
114
195
|
|
|
115
|
-
6. Verify AC after completion report:
|
|
196
|
+
6. Verify AC after the terminal completion report:
|
|
116
197
|
```bash
|
|
117
198
|
npx tsc --noEmit
|
|
118
199
|
npx vitest run src/server/ # or src/ui/
|
|
@@ -122,13 +203,9 @@ npx crewx skill wi issue WI-20260312-001
|
|
|
122
203
|
|
|
123
204
|
---
|
|
124
205
|
|
|
125
|
-
### list — List WIs
|
|
206
|
+
### Manual procedure: list — List WIs
|
|
126
207
|
|
|
127
|
-
|
|
128
|
-
npx crewx skill wi list
|
|
129
|
-
npx crewx skill wi list --status=approved
|
|
130
|
-
npx crewx skill wi list --status=in-progress
|
|
131
|
-
```
|
|
208
|
+
There is no implemented CLI route for `list`; use these repository commands manually.
|
|
132
209
|
|
|
133
210
|
**Execution:**
|
|
134
211
|
```bash
|
|
@@ -141,21 +218,16 @@ grep -l "status: approved" docs/wi/WI-*.md 2>/dev/null
|
|
|
141
218
|
|
|
142
219
|
---
|
|
143
220
|
|
|
144
|
-
### review — Request lead review
|
|
221
|
+
### Manual procedure: review — Request lead review
|
|
145
222
|
|
|
146
|
-
|
|
223
|
+
There is no implemented CLI route for `review`; request lead review manually before issuing.
|
|
147
224
|
|
|
148
|
-
|
|
149
|
-
npx crewx skill wi review WI-20260312-001
|
|
150
|
-
```
|
|
225
|
+
Request a review from the `consultant` before issuing.
|
|
151
226
|
|
|
152
227
|
```bash
|
|
153
|
-
$CREWX_CLI q
|
|
154
|
-
Check feasibility, missing items, and risks.
|
|
155
|
-
|
|
156
|
-
{entire WI file content}" \
|
|
157
|
-
--thread="WI-{ID}-review" --result="WI-{ID}-review"
|
|
228
|
+
$CREWX_CLI q --to {consultant} -f review-body.md --thread="WI-{ID}-review" --out=".crewx/result/WI-{ID}-review.txt"
|
|
158
229
|
```
|
|
230
|
+
`review-body.md` must contain the review request, review criteria, and complete WI text.
|
|
159
231
|
|
|
160
232
|
---
|
|
161
233
|
|
|
@@ -208,6 +280,7 @@ When AC fails after agent completion report:
|
|
|
208
280
|
|
|
209
281
|
## References
|
|
210
282
|
|
|
211
|
-
-
|
|
212
|
-
-
|
|
213
|
-
-
|
|
283
|
+
- Workspace WI template: `docs/wi/WI-TEMPLATE.md`
|
|
284
|
+
- Package-bundled seed: `packages/built-in/wi/templates/WI-TEMPLATE.md` (a separate file; these two templates are not claimed to be synchronized)
|
|
285
|
+
- PM guide: `skills/pm/SKILL.md`
|
|
286
|
+
- Decomposition strategy: `docs/research/multi-agent-divide-conquer.md`
|
package/dist/cli.d.ts
CHANGED
package/dist/cli.js
CHANGED
|
@@ -1,78 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
|
|
4
|
-
if (k2 === undefined) k2 = k;
|
|
5
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
-
}
|
|
9
|
-
Object.defineProperty(o, k2, desc);
|
|
10
|
-
}) : (function(o, m, k, k2) {
|
|
11
|
-
if (k2 === undefined) k2 = k;
|
|
12
|
-
o[k2] = m[k];
|
|
13
|
-
}));
|
|
14
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
-
}) : function(o, v) {
|
|
17
|
-
o["default"] = v;
|
|
18
|
-
});
|
|
19
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
-
var ownKeys = function(o) {
|
|
21
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
-
var ar = [];
|
|
23
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
-
return ar;
|
|
25
|
-
};
|
|
26
|
-
return ownKeys(o);
|
|
27
|
-
};
|
|
28
|
-
return function (mod) {
|
|
29
|
-
if (mod && mod.__esModule) return mod;
|
|
30
|
-
var result = {};
|
|
31
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
-
__setModuleDefault(result, mod);
|
|
33
|
-
return result;
|
|
34
|
-
};
|
|
35
|
-
})();
|
|
36
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
-
exports.main = main;
|
|
38
|
-
const fs = __importStar(require("fs"));
|
|
39
|
-
const path = __importStar(require("path"));
|
|
40
|
-
let PKG_VERSION = 'unknown';
|
|
41
|
-
try {
|
|
42
|
-
const _pkgPath = fs.existsSync(path.join(__dirname, 'package.json'))
|
|
43
|
-
? path.join(__dirname, 'package.json')
|
|
44
|
-
: path.join(__dirname, '..', 'package.json');
|
|
45
|
-
const _pkg = JSON.parse(fs.readFileSync(_pkgPath, 'utf-8'));
|
|
46
|
-
if (_pkg?.version)
|
|
47
|
-
PKG_VERSION = String(_pkg.version);
|
|
48
|
-
}
|
|
49
|
-
catch { }
|
|
50
|
-
async function loadTracer() {
|
|
51
|
-
try {
|
|
52
|
-
return await Promise.resolve().then(() => __importStar(require('@crewx/shared/skill-tracer')));
|
|
53
|
-
}
|
|
54
|
-
catch {
|
|
55
|
-
return null;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
function showDetailedUsage() {
|
|
59
|
-
const skillMd = path.join(__dirname, '..', 'SKILL.md');
|
|
60
|
-
if (fs.existsSync(skillMd)) {
|
|
61
|
-
process.stdout.write(fs.readFileSync(skillMd, 'utf-8'));
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
console.log('No SKILL.md found. Use --help for usage.');
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
function printUsage() {
|
|
68
|
-
console.log(`
|
|
69
|
-
@crewx/wi@${PKG_VERSION} - Structured task delegation via Work Instructions
|
|
2
|
+
"use strict";var $=exports&&exports.__createBinding||(Object.create?(function(e,t,i,s){if(s===void 0)s=i;var r=Object.getOwnPropertyDescriptor(t,i);if(!r||("get"in r?!t.__esModule:r.writable||r.configurable)){r={enumerable:true,get:function(){return t[i]}}}Object.defineProperty(e,s,r)}):(function(e,t,i,s){if(s===void 0)s=i;e[s]=t[i]}));var L=exports&&exports.__setModuleDefault||(Object.create?(function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}):function(e,t){e["default"]=t});var R=exports&&exports.__importStar||(function(){var e=function(t){e=Object.getOwnPropertyNames||function(i){var s=[];for(var r in i)if(Object.prototype.hasOwnProperty.call(i,r))s[s.length]=r;return s};return e(t)};return function(t){if(t&&t.__esModule)return t;var i={};if(t!=null){for(var s=e(t),r=0;r<s.length;r++)if(s[r]!=="default")$(i,t,s[r])}L(i,t);return i}})();Object.defineProperty(exports,"__esModule",{value:true});exports.main=x;const u=R(require("fs"));const l=R(require("path"));const S=require("@crewx/shared/crewx-api-credential");const b=require("@crewx/sdk");const M=require("@crewx/sdk/repository");const O=require("@crewx/workflow/run-manager");let P="unknown";try{const e=u.existsSync(l.join(__dirname,"package.json"))?l.join(__dirname,"package.json"):l.join(__dirname,"..","package.json");const t=JSON.parse(u.readFileSync(e,"utf-8"));if(t?.version)P=String(t.version)}catch{}async function H(){try{return await Promise.resolve().then(()=>R(require("@crewx/shared/skill-tracer")))}catch{return null}}function z(){const e=l.join(__dirname,"..","SKILL.md");if(u.existsSync(e)){process.stdout.write(u.readFileSync(e,"utf-8"))}else{console.log("No SKILL.md found. Use --help for usage.")}}function E(){console.log(`
|
|
3
|
+
@crewx/wi@${P} - Structured task delegation via Work Instructions
|
|
70
4
|
|
|
71
5
|
Usage:
|
|
72
6
|
wi <command> [args]
|
|
73
7
|
|
|
74
8
|
Commands:
|
|
75
9
|
wi usage Show detailed guide (SKILL.md)
|
|
10
|
+
wi create-batch [--file <path>] Create draft WIs from batch JSON
|
|
11
|
+
wi board tick <brd-id> [--json] Advance one approved board WI if gates pass
|
|
12
|
+
wi board digest <brd-id> [--json] Send and print the overnight board summary
|
|
76
13
|
wi draft <description> Draft a new Work Instruction (planned)
|
|
77
14
|
wi issue <WI-ID> Issue WI to assigned agent (planned)
|
|
78
15
|
wi list [--status=...] List Work Instructions (planned)
|
|
@@ -82,42 +19,8 @@ Options:
|
|
|
82
19
|
--version Show version
|
|
83
20
|
--help, -h Show this help
|
|
84
21
|
|
|
85
|
-
Note:
|
|
86
|
-
Phase 1 — only 'usage' is available. Other subcommands are planned.
|
|
87
|
-
|
|
88
22
|
Template: docs/wi/WI-TEMPLATE.md
|
|
89
23
|
For detailed usage guide: wi usage
|
|
90
|
-
`);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const args = inputArgs ?? process.argv.slice(2);
|
|
94
|
-
const command = args[0];
|
|
95
|
-
if (args.includes('--version')) {
|
|
96
|
-
console.log(PKG_VERSION);
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
if (args.includes('--help') || args.includes('-h')) {
|
|
100
|
-
printUsage();
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
if (command === 'usage') {
|
|
104
|
-
showDetailedUsage();
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
if (command === 'draft' || command === 'issue' || command === 'list' || command === 'review') {
|
|
108
|
-
console.log(`\n '${command}' is not yet implemented (Phase 1).\n`);
|
|
109
|
-
console.log(` Run 'wi usage' for the full guide.\n`);
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
printUsage();
|
|
113
|
-
}
|
|
114
|
-
if (require.main === module) {
|
|
115
|
-
loadTracer().then(tracer => {
|
|
116
|
-
const opts = tracer ? { skillVersion: tracer.getOwnSkillVersion(__dirname) } : {};
|
|
117
|
-
return tracer ? tracer.run('crewx/wi', () => main(), opts) : main();
|
|
118
|
-
}).catch((e) => {
|
|
119
|
-
console.error(e.message);
|
|
120
|
-
process.exit(1);
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
//# sourceMappingURL=cli.js.map
|
|
24
|
+
`)}const K=new Set(["help","version","json"]);function G(e){const t={positional:[],options:{}};for(let i=0;i<e.length;i++){const s=e[i];if(s==="-h"){t.options["help"]=true}else if(s.startsWith("--")){const r=s.indexOf("=");if(r!==-1){t.options[s.slice(2,r)]=s.slice(r+1)}else{const a=s.slice(2);if(K.has(a)){t.options[a]=true}else{const n=e[i+1];if(n!==void 0&&!n.startsWith("--")){t.options[a]=n;i++}else{t.options[a]=true}}}}else{t.positional.push(s)}}return t}async function U(){const e=[];for await(const t of process.stdin)e.push(t);return Buffer.concat(e).toString("utf-8")}function g(){return l.resolve(process.env["CREWX_WORKSPACE"]||process.cwd())}function X(e){const t=JSON.parse(e);if(!t||typeof t!=="object"||Array.isArray(t)){throw new Error("Input must be a JSON object")}return t}async function V(e){const t=e["file"];const i=typeof t==="string"?u.readFileSync(l.resolve(t),"utf-8"):await U();const s=X(i);const r=await(0,b.createWorkInstructionBatch)(g(),s);process.stdout.write(JSON.stringify({created:r.created.map(a=>({wi_id:a.summary.wi_id,title:a.summary.title}))})+"\n")}function F(){return{batch:{wiIds:[],approvedAt:null},chain:{state:"idle",currentWiId:null,nextWiId:null,nextTickAt:null,pauseReason:null,resumeAt:null,consecutiveFailures:0,queue:[],budget:{usedPercent:0,capPercent:70,resetsAt:null},sessionSummary:{completed:0,needsFeedback:0,failed:0,skippedTicks:0}},updatedAt:new Date().toISOString()}}function Z(e){const t=F();if(!e||typeof e!=="object")return t;const i=e;return{...t,...i,batch:{...t.batch,...i.batch??{}},chain:{...t.chain,...i.chain??{},budget:{...t.chain.budget,...i.chain?.budget??{}},sessionSummary:{...t.chain.sessionSummary,...i.chain?.sessionSummary??{}},queue:Array.isArray(i.chain?.queue)?i.chain.queue:t.chain.queue}}}function A(e){return l.join(g(),".crewx","boards",e,"state.json")}function D(e){if(!b.WI_BOARD_ID_PATTERN.test(e)){throw new Error("board id must match ^[a-zA-Z0-9_-]{1,64}$")}}function k(e){const t=A(e);if(!u.existsSync(t))return F();return Z(JSON.parse(u.readFileSync(t,"utf-8")))}function p(e,t){t.updatedAt=new Date().toISOString();const i=A(e);u.mkdirSync(l.dirname(i),{recursive:true});u.writeFileSync(i,JSON.stringify(t,null,2)+"\n","utf-8")}function Q(e){if(!e.startsWith("---"))return null;const t=e.indexOf("\n---",3);if(t===-1)return null;const i=e.indexOf("\n",t+4);return{frontmatter:e.slice(3,t).trim(),body:i===-1?"":e.slice(i+1).trim()}}function B(e){const t=e.trim();if(t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'")){try{return JSON.parse(t)}catch{return t.slice(1,-1)}}return t}function Y(e){const t={};const i=e.split(/\r?\n/);for(let s=0;s<i.length;s++){const r=i[s];const a=r.match(/^([A-Za-z_][\w-]*):\s*(.*)$/);if(!a)continue;const n=a[1];const o=a[2];if(o===""){const c=[];while(s+1<i.length&&/^\s+-\s+/.test(i[s+1])){s++;c.push(B(i[s].replace(/^\s+-\s+/,"")))}t[n]=c}else if(o==="[]"){t[n]=[]}else{t[n]=B(o)}}return t}function ee(e){if(Array.isArray(e))return e.map(String);if(e===void 0||e===null||e==="")return[];return[String(e)]}function C(){const e=l.join(g(),"docs","wi");if(!u.existsSync(e))return[];const t=u.readdirSync(e).filter(s=>s.endsWith(".md")&&/^WI-\d{8}-\d+/.test(s));const i=[];for(const s of t){const r=l.join(e,s);const a=u.lstatSync(r);if(!a.isFile())continue;const n=u.readFileSync(r,"utf-8");const o=Q(n);if(!o)continue;const c=Y(o.frontmatter);const f=typeof c["wi_id"]==="string"?c["wi_id"]:"";const w=typeof c["status"]==="string"?c["status"]:"draft";if(!/^WI-\d{8}-\d+$/.test(f))continue;if(!["draft","approved","in-progress","done","cancelled"].includes(w))continue;i.push({wi_id:f,title:typeof c["title"]==="string"?c["title"]:"",status:w,depends_on:ee(c["depends_on"]),assignee:typeof c["assignee"]==="string"?c["assignee"]:void 0,board:typeof c["board"]==="string"?c["board"]:void 0,source:typeof c["source"]==="string"?c["source"]:"manual",path:l.join("docs","wi",s),body:o.body})}return i}function te(){return l.join(g(),"workflows","wi-default-flow.yaml")}function j(e){return e.status==="completed"||e.status==="failed"||e.status==="cancelled"}function q(e){const t=l.join(g(),".crewx","workflow-runs");if(!u.existsSync(t))return[];const i=new Set(e);return u.readdirSync(t).filter(s=>s.endsWith(".json")).flatMap(s=>{try{const r=JSON.parse(u.readFileSync(l.join(t,s),"utf-8"));const a=typeof r.initial_state?.["wi_id"]==="string"?r.initial_state["wi_id"]:typeof r.state?.["wi_id"]==="string"?r.state["wi_id"]:"";return i.has(a)?[r]:[]}catch{return[]}})}function I(e,t){if(!e.current_node||j(e))return false;return t.getNodeType(e.workflow_file,e.workflow_id,e.current_node)==="approval"}function ne(){const e=process.env["CREWX_WI_NIGHT_START"];const t=process.env["CREWX_WI_NIGHT_END"];if(e===void 0||t===void 0)return null;const i=Number(e);const s=Number(t);if(!Number.isInteger(i)||!Number.isInteger(s))return null;if(i<0||i>23||s<0||s>23)return null;return{start:i,end:s}}function ie(e,t){if(e.start===e.end)return true;const i=t.getHours();return e.start<e.end?i>=e.start&&i<e.end:i>=e.start||i<e.end}function se(e,t){const i=new Date(t);i.setHours(e.start,0,0,0);if(i.getTime()<=t.getTime())i.setDate(i.getDate()+1);return i}function re(e,t){if(e.chain.nextTickAt){const s=Date.parse(e.chain.nextTickAt);if(!Number.isNaN(s)&&s>t.getTime()){return{paused:true,resumeAt:e.chain.nextTickAt}}}const i=ne();if(i&&!ie(i,t)){return{paused:true,resumeAt:se(i,t).toISOString()}}return{paused:false}}function v(e,t,i=new Map){e.chain.queue=e.batch.wiIds.map((s,r)=>{const a=t.some(n=>n.wi_id===s);return{wiId:s,queuePosition:r+1,blockReason:i.get(s)??(a?null:"missing")}})}const ae={codex:["fiveHour","weekly"],claude:["fiveHour","sevenDay"],glm:["fiveHour","weekly"],grok:["weekly","monthly"]};function W(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}function oe(e){if(!W(e))return null;if(!Object.prototype.hasOwnProperty.call(e,"usedPercent")||!Object.prototype.hasOwnProperty.call(e,"resetsAt")){return null}const t=e["usedPercent"];const i=e["resetsAt"];if(typeof t!=="number"||!Number.isFinite(t)||t<0||t>100){return null}if(i!==null&&(typeof i!=="string"||!Number.isFinite(Date.parse(i)))){return null}return{usedPercent:t,resetsAt:i}}function ce(e){if(!W(e))return[];const t=[];for(const[i,s]of Object.entries(ae)){const r=e[i];if(!W(r))continue;if(r["status"]!=="live"&&r["status"]!=="cached")continue;if(!W(r["data"]))continue;for(const a of s){const n=oe(r["data"][a]);if(n)t.push(n)}}return t}function ue(e){const t=l.basename(e).toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/-{2,}/g,"-").replace(/^-+|-+$/g,"");return t||"default"}function le(){const e=g();try{const t=new M.WorkspaceRepository;const i=(0,b.hashWorkspaceId)(e);const s=t.findById(i);if(s?.slug)return s.slug;const r=t.registerWorkspace(e);if(r?.slug)return r.slug}catch{}return ue(e)}async function de(e){const t=process.env["CREWX_ENDPOINT"]??"http://localhost:8150";const i=le();const s=(0,S.resolveCrewxApiCredential)("wi");let r;try{r=await fetch(`${t}/api/v1/ws/${encodeURIComponent(i)}/usage/limits`,{headers:(0,S.authorizationHeader)(s),signal:AbortSignal.timeout(5e3)})}catch(c){return{ok:false,usedPercent:0,resetsAt:null,reason:`usage limits unavailable: ${c instanceof Error?c.message:String(c)}`}}if(!r.ok){return{ok:false,usedPercent:0,resetsAt:null,reason:`usage limits unavailable: HTTP ${r.status}`}}let a=null;try{const c=await r.json();a=W(c)?c:null}catch{}const n=ce(a?.["data"]);if(n.length===0){return{ok:false,usedPercent:0,resetsAt:null,reason:"usage limits unavailable: empty response"}}const o=n.reduce((c,f)=>f.usedPercent>c.usedPercent?f:c,n[0]);return{ok:o.usedPercent<e,usedPercent:o.usedPercent,resetsAt:o.resetsAt,...o.usedPercent>=e?{reason:`budget cap reached (${o.usedPercent}% >= ${e}%)`}:{}}}async function y(e,t){const i=process.env["CREWX_WORKSPACE"]||g();const s=process.env["CREWX_ENDPOINT"]??"http://localhost:8150";const r=(0,S.resolveCrewxApiCredential)("wi");const a={"Content-Type":"application/json",...(0,S.authorizationHeader)(r)};try{const n=await fetch(`${s}/api/v1/notifications`,{method:"POST",headers:a,body:JSON.stringify({workspace:i,title:e,level:t.level??"info",body:t.body,source:"system",metadata:t.metadata}),signal:AbortSignal.timeout(5e3)});if(!n.ok){const o=await n.text().catch(()=>"");console.error(`[wi] notification failed: HTTP ${n.status}${o?` ${o}`:""}`)}}catch(n){console.error(`[wi] notification failed: ${n instanceof Error?n.message:String(n)}`)}}async function fe(e,t){D(e);const i=new O.FileLock(A(e));try{i.acquire(100)}catch{const n={skipped:true,reason:"lock_contended"};process.stdout.write(JSON.stringify(n)+"\n");return}const s=new O.RunManager(".crewx/workflow-runs",g());let r=null;try{const n=k(e);const o=new Date;const c=re(n,o);if(c.paused){n.chain.pauseReason="time_gate";n.chain.nextTickAt=c.resumeAt;n.chain.resumeAt=c.resumeAt;n.chain.sessionSummary.skippedTicks+=1;p(e,n);process.stdout.write(JSON.stringify({skipped:true,reason:"time_gate",state:n})+"\n");return}const f=await de(n.chain.budget.capPercent);n.chain.budget.usedPercent=f.usedPercent;n.chain.budget.resetsAt=f.resetsAt;if(!f.ok){n.chain.state="limit_wait";n.chain.pauseReason=f.reason??"budget_limit";n.chain.resumeAt=f.resetsAt;n.chain.sessionSummary.skippedTicks+=1;p(e,n);process.stdout.write(JSON.stringify({skipped:true,reason:n.chain.pauseReason,state:n})+"\n");return}const w=C().filter(d=>n.batch.wiIds.includes(d.wi_id));v(n,w);const T=q(n.batch.wiIds).filter(d=>!j(d));const N=T.find(d=>!I(d,s));if(N){n.chain.state="running";n.chain.currentWiId=String(N.state?.["wi_id"]??N.initial_state?.["wi_id"]??"");n.chain.pauseReason="run_in_progress";p(e,n);process.stdout.write(JSON.stringify({skipped:true,reason:"run_in_progress",state:n})+"\n");return}const _=new Set(T.filter(d=>I(d,s)).map(d=>String(d.state?.["wi_id"]??d.initial_state?.["wi_id"]??"")));const h=(0,b.selectNextWi)(w,{batch:n.batch.wiIds,exclude:[..._]});if("blocked"in h){n.chain.state="failed_stop";n.chain.pauseReason=h.reason;v(n,w);p(e,n);await y("Board auto-run stopped",{level:"warning",body:h.reason,metadata:{boardId:e}});process.stdout.write(JSON.stringify({blocked:true,reason:h.reason,state:n})+"\n");return}if("cycle"in h){n.chain.state="failed_stop";n.chain.pauseReason=`cycle: ${h.cycle.join(", ")}`;v(n,w);p(e,n);await y("Board auto-run stopped",{level:"warning",body:n.chain.pauseReason,metadata:{boardId:e}});process.stdout.write(JSON.stringify({cycle:h.cycle,state:n})+"\n");return}if("done"in h){n.chain.state=_.size>0?"human_wait":"done";n.chain.currentWiId=null;n.chain.nextWiId=null;n.chain.pauseReason=_.size>0?"approval_wait":null;v(n,w,new Map([..._].map(d=>[d,"approval_wait"])));p(e,n);process.stdout.write(JSON.stringify({done:_.size===0,state:n})+"\n");return}const m=w.find(d=>d.wi_id===h.pick);if(!m)throw new Error(`Selected WI not found: ${h.pick}`);const J=s.start(te(),"wi-default-flow",{wi_id:m.wi_id,wi_content:m.body,assignee:m.assignee??"crewx",board_id:e});n.chain.state="running";n.chain.currentWiId=m.wi_id;n.chain.nextWiId=null;n.chain.pauseReason=null;p(e,n);r={wiId:m.wi_id,runId:J.id}}catch(n){const o=k(e);o.chain.consecutiveFailures+=1;o.chain.sessionSummary.failed+=1;o.chain.pauseReason=n instanceof Error?n.message:String(n);o.chain.state=o.chain.consecutiveFailures>=3?"failed_stop":"idle";p(e,o);if(o.chain.state==="failed_stop"){await y("Board auto-run stopped",{level:"warning",body:o.chain.pauseReason??"run_failed",metadata:{boardId:e}})}throw n}finally{i.release()}if(!r)return;let a;try{a=await s.runAuto(r.runId)}catch(n){a={run:s.loadRun(r.runId),outcome:"failed",reason:n instanceof Error?n.message:String(n),executed:[]}}i.acquire();try{const n=k(e);const o=C().filter(c=>n.batch.wiIds.includes(c.wi_id));if(a.outcome==="completed"){n.chain.state="idle";n.chain.currentWiId=null;n.chain.consecutiveFailures=0;n.chain.sessionSummary.completed+=1}else if(a.outcome==="paused"){n.chain.state=a.reason?.includes("approval node")?"human_wait":"idle";n.chain.pauseReason=a.reason??null}else if(a.outcome==="failed"){n.chain.consecutiveFailures+=1;n.chain.sessionSummary.failed+=1;n.chain.state=n.chain.consecutiveFailures>=3?"failed_stop":"idle";n.chain.pauseReason=a.reason??"run_failed";if(n.chain.state==="failed_stop"){await y("Board auto-run stopped",{level:"warning",body:n.chain.pauseReason,metadata:{boardId:e}})}}v(n,o);p(e,n);process.stdout.write(JSON.stringify({started:r.wiId,runId:r.runId,outcome:a.outcome,state:n})+"\n")}catch(n){const o=k(e);o.chain.consecutiveFailures+=1;o.chain.sessionSummary.failed+=1;o.chain.pauseReason=n instanceof Error?n.message:String(n);o.chain.state=o.chain.consecutiveFailures>=3?"failed_stop":"idle";p(e,o);if(o.chain.state==="failed_stop"){await y("Board auto-run stopped",{level:"warning",body:o.chain.pauseReason??"run_failed",metadata:{boardId:e}})}throw n}finally{i.release()}}async function pe(e,t){D(e);const i=new O.FileLock(A(e));i.acquire();try{const s=k(e);const r=new O.RunManager(".crewx/workflow-runs",g());const a=q(s.batch.wiIds).filter(n=>!j(n));s.chain.sessionSummary.needsFeedback=a.filter(n=>I(n,r)).length;p(e,s);await y("Overnight auto-run summary",{level:"info",body:JSON.stringify(s.chain.sessionSummary),metadata:{boardId:e}});process.stdout.write(JSON.stringify({boardId:e,sessionSummary:s.chain.sessionSummary,metadata:{boardId:e}})+"\n")}finally{i.release()}}async function x(e){const t=e??process.argv.slice(2);const{positional:i,options:s}=G(t);const r=i[0];if(s["version"]){console.log(P);return}if(s["help"]||r==="help"){E();return}if(r==="usage"){z();return}try{if(r==="create-batch"){await V(s);return}if(r==="board"){const a=i[1];const n=i[2];if(!n||a!=="tick"&&a!=="digest"){throw new Error("Usage: wi board <tick|digest> <brd-id>")}if(a==="tick"){await fe(n,s)}else{await pe(n,s)}return}}catch(a){if(a instanceof b.WiCreateError)throw new Error(a.message);throw a}if(r==="draft"||r==="issue"||r==="list"||r==="review"){console.log(`
|
|
25
|
+
'${r}' is not yet implemented.
|
|
26
|
+
`);console.log(" Run 'wi usage' for the full guide.\n");return}E()}if(typeof require!=="undefined"&&require.main===module){H().then(e=>{const t=e?{skillVersion:e.getOwnSkillVersion(__dirname)}:{};return e?e.run("crewx/wi",()=>x(),t):x()}).catch(e=>{console.error(e.message);process.exit(e instanceof S.CrewxCredentialError?e.exitCode:1)})}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crewx/wi",
|
|
3
|
-
"version": "0.1.10-rc.
|
|
3
|
+
"version": "0.1.10-rc.191",
|
|
4
4
|
"description": "Work Instruction engine for CrewX - structured task delegation",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "dist/cli.js",
|
|
@@ -25,9 +25,21 @@
|
|
|
25
25
|
"templates/"
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@crewx/
|
|
28
|
+
"@crewx/sdk": "0.9.0-rc.171",
|
|
29
|
+
"@crewx/workflow": "0.3.22-rc.217",
|
|
30
|
+
"@crewx/shared": "0.0.6-rc.86"
|
|
31
|
+
},
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"better-sqlite3": ">=12.0.0"
|
|
34
|
+
},
|
|
35
|
+
"peerDependenciesMeta": {
|
|
36
|
+
"better-sqlite3": {
|
|
37
|
+
"optional": true
|
|
38
|
+
}
|
|
29
39
|
},
|
|
30
40
|
"devDependencies": {
|
|
41
|
+
"@types/better-sqlite3": "*",
|
|
42
|
+
"better-sqlite3": "12.8.0",
|
|
31
43
|
"@types/node": "^20.0.0",
|
|
32
44
|
"typescript": "^5.0.0"
|
|
33
45
|
},
|
package/dist/cli.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":";AAqDA,wBAAsB,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA0B9D"}
|
package/dist/cli.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":"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"}
|