@brainervirus/workit-cli 4.0.0 → 5.0.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.
|
@@ -1,27 +1,26 @@
|
|
|
1
|
-
# <Feature>
|
|
1
|
+
# <Feature> plan
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Spec: `docs/<slug>/spec.md` · Goal: <one sentence>
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
A plan records decisions, not code: per slice the branch, what it touches, its
|
|
6
|
+
acceptance, how it is verified, and what it depends on (workit-shape
|
|
7
|
+
`references/slicing.md`). Independent slices fan out (workit-fanout);
|
|
8
|
+
dependent ones stack (`workit stack plan <bottom> … <top>`).
|
|
7
9
|
|
|
8
|
-
|
|
10
|
+
## Global constraints
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
- Each task lands exactly one contiguous non-empty commit range (`base..head`): fix rounds append commits to that range and never rewrite/amend an active review range; record the real base..head shas in task progress.
|
|
13
|
-
- The final task closes the lead Workit task with `workit_task` `action: "close"` (CLI: `workit task close --payload … [--confirm]`) once requirements are satisfied and repository verification passes — never finish while the task is still `active` or `paused`.
|
|
14
|
-
- <project-wide requirements, one line each>
|
|
12
|
+
- <project-wide requirement, one line each>
|
|
15
13
|
|
|
16
14
|
---
|
|
17
15
|
|
|
18
|
-
###
|
|
19
|
-
|
|
20
|
-
- [ ] **Step 1: <action>**
|
|
16
|
+
### S1 <type>/<slug> (base: main)
|
|
21
17
|
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
Touches: <areas, not line numbers>
|
|
19
|
+
Acceptance:
|
|
20
|
+
- Given <state>, When <action>, Then <observable result>
|
|
21
|
+
Verify: `workit check test`; verify-<app> "<feature>"
|
|
22
|
+
Decisions: <ledger refs or one-line rulings>
|
|
24
23
|
|
|
25
|
-
|
|
|
26
|
-
| --- | --- |
|
|
27
|
-
|
|
|
24
|
+
| Slice | Branch | Depends on | Status |
|
|
25
|
+
| --- | --- | --- | --- |
|
|
26
|
+
| S1 | <type>/<slug> | — | pending |
|
|
@@ -19,14 +19,15 @@ no durable agreement: `Spec: none (<reason>)`, no file.)
|
|
|
19
19
|
|
|
20
20
|
## Architecture
|
|
21
21
|
|
|
22
|
-
<!--
|
|
23
|
-
|
|
22
|
+
<!-- Optional: only when a diagram argues a decision (workit-shape
|
|
23
|
+
references/diagrams.md); otherwise delete this section. -->
|
|
24
24
|
```mermaid
|
|
25
25
|
flowchart TD
|
|
26
26
|
A[Start] --> B[Step]
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
<!--
|
|
29
|
+
<!-- Optional: a UI choice still open gets an ASCII sketch (workit-shape
|
|
30
|
+
references/mockups.md). -->
|
|
30
31
|
```text
|
|
31
32
|
┌──────────────┐
|
|
32
33
|
│ Header │
|
package/dist/index.js
CHANGED
|
@@ -65,7 +65,7 @@ var package_default;
|
|
|
65
65
|
var init_package = __esm(() => {
|
|
66
66
|
package_default = {
|
|
67
67
|
name: "@brainervirus/workit-cli",
|
|
68
|
-
version: "
|
|
68
|
+
version: "4.0.0",
|
|
69
69
|
private: false,
|
|
70
70
|
description: "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
|
|
71
71
|
keywords: [
|
|
@@ -15598,13 +15598,13 @@ var METHODS, methodMatches = (definition, requirement) => definition.dimensions?
|
|
|
15598
15598
|
};
|
|
15599
15599
|
var init_methods = __esm(() => {
|
|
15600
15600
|
METHODS = {
|
|
15601
|
-
"workit-
|
|
15602
|
-
"workit-
|
|
15601
|
+
"workit-shape": { dimensions: ["challenge", "decisions", "artifacts", "continuity"] },
|
|
15602
|
+
"workit-bdd": { dimensions: ["testing"] },
|
|
15603
15603
|
"workit-review": { dimensions: ["review"], ruleIds: ["fresh-context-review", "self-review"] },
|
|
15604
|
-
"workit-
|
|
15605
|
-
"workit-
|
|
15604
|
+
"workit-implement": { ruleIds: ["mechanical-existing-checks"] },
|
|
15605
|
+
"workit-fanout": { dimensions: ["delegation"] },
|
|
15606
15606
|
"workit-debug": {},
|
|
15607
|
-
"workit-
|
|
15607
|
+
"workit-continue": {},
|
|
15608
15608
|
"workit-deslop": { ruleIds: ["pre-pr-cleanup"] }
|
|
15609
15609
|
};
|
|
15610
15610
|
});
|
|
@@ -21627,10 +21627,15 @@ function recordVerdict(context, input) {
|
|
|
21627
21627
|
if (key.dirty === true)
|
|
21628
21628
|
return err("blocked", `dirty_worktree: ${branch} has uncommitted changes, so its head is not what was judged`, "commit or stash the changes, re-check, then record the verdict");
|
|
21629
21629
|
const session = context.actor.session;
|
|
21630
|
-
const selfReason = input.self === true ? "flag" : session ? null : "no_session";
|
|
21630
|
+
const selfReason = input.self === true ? "flag" : session && input.derivedFrom !== null ? null : "no_session";
|
|
21631
21631
|
const self2 = selfReason !== null;
|
|
21632
|
-
|
|
21633
|
-
|
|
21632
|
+
const authors = authorSessions(context.cwd, ledger.value.rows, branch, {
|
|
21633
|
+
base: key.base,
|
|
21634
|
+
head: key.head
|
|
21635
|
+
});
|
|
21636
|
+
const authoring = [session, input.derivedFrom].find((candidate) => typeof candidate === "string" && authors.has(candidate));
|
|
21637
|
+
if (!self2 && authoring)
|
|
21638
|
+
return err("blocked", `author_verdict: session ${authoring} authored ${branch}; a verdict must come from a different session`, input.derivedFrom === undefined ? 'have a non-author session record the verdict, or pass --self (a self verdict is never accepted by merge:"verified")' : "run the verifier as a separate session: the lead spawns it with its own WORKIT_SESSION_ID (Claude Code: subagents get one from the SubagentStart hook)");
|
|
21634
21639
|
const link = checkSupersede(context, "verdict", self2);
|
|
21635
21640
|
if (!link.ok)
|
|
21636
21641
|
return link;
|
|
@@ -23602,7 +23607,7 @@ var run3 = (root, args) => {
|
|
|
23602
23607
|
cwd: target.data
|
|
23603
23608
|
}
|
|
23604
23609
|
});
|
|
23605
|
-
}, prBabysitNext = (output) => `PR ready: ${output}. Babysitting was explicitly requested. Follow workit-
|
|
23610
|
+
}, prBabysitNext = (output) => `PR ready: ${output}. Babysitting was explicitly requested. Follow workit-ship to resolve conflicts, review threads, and get checks green. Stop at PR-ready; a PR or babysit request does not authorize merge or release.`, executeConcreteExternalAction = async (request, root, marker, dateMs, step, workText, caller, approvedBeforeDigest, approvedBeforeExists, coordinationRoot = root, approvedTip, approvedRemote, approvedAccount, approvedApiHost, approvedSourceCommit, approvedCommit, approvedRemoteBase, approvedLocalBase, writerActionLease, approvedSourceBranch, approvedMergeBaseCommit, expectedWorkspaceRevision) => {
|
|
23606
23611
|
if (localAction(request.operation)) {
|
|
23607
23612
|
if (!caller)
|
|
23608
23613
|
return failure2("capability_unavailable", "local external action writer authority is unavailable", { outcome: "not_started" });
|
|
@@ -23717,7 +23722,7 @@ var run3 = (root, args) => {
|
|
|
23717
23722
|
...result,
|
|
23718
23723
|
...request.payload.babysit !== undefined ? { babysit: request.payload.babysit } : {},
|
|
23719
23724
|
...babysit ? {
|
|
23720
|
-
babysitSkill: "workit-
|
|
23725
|
+
babysitSkill: "workit-ship",
|
|
23721
23726
|
next: prBabysitNext(String(result.output ?? ""))
|
|
23722
23727
|
} : {}
|
|
23723
23728
|
});
|
|
@@ -68239,22 +68244,17 @@ var WORKIT_METHOD_SKILLS, skillManifestNames = (root) => existsSync12(root) ? re
|
|
|
68239
68244
|
};
|
|
68240
68245
|
var init_skill_manifests = __esm(() => {
|
|
68241
68246
|
WORKIT_METHOD_SKILLS = [
|
|
68242
|
-
"workit-
|
|
68243
|
-
"workit-behavioral-tdd",
|
|
68244
|
-
"workit-review",
|
|
68245
|
-
"workit-plan",
|
|
68247
|
+
"workit-shape",
|
|
68246
68248
|
"workit-implement",
|
|
68249
|
+
"workit-review",
|
|
68247
68250
|
"workit-debug",
|
|
68248
|
-
"workit-
|
|
68249
|
-
"workit-
|
|
68250
|
-
"workit-blast-radius",
|
|
68251
|
-
"workit-deslop",
|
|
68252
|
-
"workit-diagram",
|
|
68253
|
-
"workit-mockup",
|
|
68254
|
-
"workit-green-run",
|
|
68255
|
-
"workit-steer",
|
|
68251
|
+
"workit-ship",
|
|
68252
|
+
"workit-continue",
|
|
68256
68253
|
"workit-bdd",
|
|
68257
|
-
"workit-test-audit"
|
|
68254
|
+
"workit-test-audit",
|
|
68255
|
+
"workit-deslop",
|
|
68256
|
+
"workit-fanout",
|
|
68257
|
+
"workit-verify-app"
|
|
68258
68258
|
];
|
|
68259
68259
|
if (false) {}
|
|
68260
68260
|
});
|
|
@@ -68531,8 +68531,11 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
68531
68531
|
}, assetPathsFor = (host, dev) => {
|
|
68532
68532
|
const pkg = path32.join(dev, "packages", `workit-${host}`);
|
|
68533
68533
|
switch (host) {
|
|
68534
|
-
case "opencode":
|
|
68535
|
-
|
|
68534
|
+
case "opencode": {
|
|
68535
|
+
const packaged = path32.join(pkg, "assets", "skills");
|
|
68536
|
+
const root = existsSync13(packaged) ? packaged : path32.join(dev, "packages", "workit-core", "skills");
|
|
68537
|
+
return WORKIT_METHOD_SKILLS.map((skill) => path32.join(root, skill, "SKILL.md"));
|
|
68538
|
+
}
|
|
68536
68539
|
case "cursor":
|
|
68537
68540
|
return [
|
|
68538
68541
|
path32.join(pkg, "assets", "templates", "workit-contract.md"),
|
|
@@ -79819,6 +79822,7 @@ var exports_ledger = {};
|
|
|
79819
79822
|
__export(exports_ledger, {
|
|
79820
79823
|
run: () => run18
|
|
79821
79824
|
});
|
|
79825
|
+
import { randomBytes as randomBytes4 } from "node:crypto";
|
|
79822
79826
|
import { parseArgs } from "node:util";
|
|
79823
79827
|
function targetBranch(io, rows, branch, pr) {
|
|
79824
79828
|
if (pr !== undefined) {
|
|
@@ -79901,9 +79905,13 @@ async function run18(argv, io) {
|
|
|
79901
79905
|
const target = targetBranch(io, rows, values.branch, pr);
|
|
79902
79906
|
if (!target.ok)
|
|
79903
79907
|
return failed(io, target);
|
|
79908
|
+
const acting = actorFor(io, values);
|
|
79909
|
+
if (acting instanceof Error)
|
|
79910
|
+
return usage3(io, acting.message);
|
|
79911
|
+
const { actor } = acting;
|
|
79904
79912
|
const context = {
|
|
79905
79913
|
cwd: io.cwd,
|
|
79906
|
-
actor
|
|
79914
|
+
actor,
|
|
79907
79915
|
branch: target.value,
|
|
79908
79916
|
base: values.base ?? null,
|
|
79909
79917
|
...pr === undefined ? {} : { pr },
|
|
@@ -79931,10 +79939,30 @@ async function run18(argv, io) {
|
|
|
79931
79939
|
how: values.how,
|
|
79932
79940
|
surface: values.surface ?? null,
|
|
79933
79941
|
self: values.self === true,
|
|
79934
|
-
evidenceRefs: values.evidence
|
|
79935
|
-
|
|
79942
|
+
evidenceRefs: values.evidence,
|
|
79943
|
+
..."derivedFrom" in acting ? { derivedFrom: acting.derivedFrom } : {}
|
|
79944
|
+
})), (row) => `recorded verdict ${row.id}: ${row.result} [${row.kind}] for ${row.branch} @ ${(row.head ?? "").slice(0, 12)} as ${actor.session ?? "no session"}${row.self ? ` (self${row.selfReason === "no_session" ? ": WORKIT_SESSION_ID unset" : ""}; never accepted)` : ""}`);
|
|
79936
79945
|
}
|
|
79937
|
-
var USAGE7 = "workit ledger decision|ruling|verdict|list|check ... (workit help ledger for the grammar)", OPTIONS,
|
|
79946
|
+
var USAGE7 = "workit ledger decision|ruling|verdict|list|check ... (workit help ledger for the grammar)", OPTIONS, SESSION_SAFE2, ROLE_SAFE, actorFor = (io, values) => {
|
|
79947
|
+
const actor = actorFromEnv(io.env);
|
|
79948
|
+
if (values.session !== undefined && values.as !== undefined)
|
|
79949
|
+
return new Error("pass --session or --as, not both");
|
|
79950
|
+
if (values.session !== undefined) {
|
|
79951
|
+
if (!SESSION_SAFE2.test(values.session))
|
|
79952
|
+
return new Error("--session must be 1-128 characters of [A-Za-z0-9_.:@/+-]");
|
|
79953
|
+
return { actor: { ...actor, session: values.session } };
|
|
79954
|
+
}
|
|
79955
|
+
if (values.as !== undefined) {
|
|
79956
|
+
if (!ROLE_SAFE.test(values.as))
|
|
79957
|
+
return new Error("--as takes a lowercase role, e.g. verifier");
|
|
79958
|
+
const prefix = (actor.session ?? actor.host).slice(0, 96);
|
|
79959
|
+
return {
|
|
79960
|
+
actor: { ...actor, session: `${prefix}:${values.as}:${randomBytes4(4).toString("hex")}` },
|
|
79961
|
+
derivedFrom: actor.session
|
|
79962
|
+
};
|
|
79963
|
+
}
|
|
79964
|
+
return { actor };
|
|
79965
|
+
}, positiveInt2 = (value, flag) => {
|
|
79938
79966
|
if (value === undefined)
|
|
79939
79967
|
return;
|
|
79940
79968
|
const parsed = Number(value);
|
|
@@ -79967,8 +79995,12 @@ var init_ledger2 = __esm(() => {
|
|
|
79967
79995
|
type: { type: "string" },
|
|
79968
79996
|
last: { type: "string" },
|
|
79969
79997
|
supersedes: { type: "string" },
|
|
79998
|
+
session: { type: "string" },
|
|
79999
|
+
as: { type: "string" },
|
|
79970
80000
|
json: { type: "boolean" }
|
|
79971
80001
|
};
|
|
80002
|
+
SESSION_SAFE2 = /^[A-Za-z0-9_.:@/+-]{1,128}$/;
|
|
80003
|
+
ROLE_SAFE = /^[a-z][a-z0-9-]{0,31}$/;
|
|
79972
80004
|
});
|
|
79973
80005
|
|
|
79974
80006
|
// node_modules/@babel/parser/lib/index.js
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainervirus/workit-cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
|
|
6
6
|
"keywords": [
|
|
@@ -38,9 +38,9 @@
|
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@babel/parser": "7.29.9",
|
|
41
|
-
"@brainervirus/workit-core": "^
|
|
42
|
-
"@brainervirus/workit-cursor": "^
|
|
43
|
-
"@brainervirus/workit-opencode": "^
|
|
41
|
+
"@brainervirus/workit-core": "^5.0.0",
|
|
42
|
+
"@brainervirus/workit-cursor": "^5.0.0",
|
|
43
|
+
"@brainervirus/workit-opencode": "^5.0.0",
|
|
44
44
|
"@inkjs/ui": "2.0.0",
|
|
45
45
|
"ink": "7.1.1",
|
|
46
46
|
"react": "19.2.8"
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
Load resolved method skills through the host skill loader when policy selects them. Implement the existing plan; do not re-plan.
|
|
2
|
-
|
|
3
|
-
**Spec:** <SPEC_PATH>
|
|
4
|
-
**Plan:** <PLAN_PATH>
|
|
5
|
-
**Branch:** <BRANCH>
|
|
6
|
-
|
|
7
|
-
## Hard gates
|
|
8
|
-
|
|
9
|
-
- Inspect task state before acting. On OpenCode, Cursor, Codex, and Pi use the eight shared `workit_*` families (`workit_task`, `workit_policy`, `workit_evidence`, `workit_finding`, `workit_decision`, `workit_worker`, `workit_writer`, `workit_state`). On the CLI host use `workit <family> <action>` with the same actions (hyphenated on the CLI).
|
|
10
|
-
- Never use a worktree. Branch changes are in-place through the approved `git.branch_setup` external action (CLI: `workit action git.branch_setup --payload …`).
|
|
11
|
-
- Task metadata lives under `.workit/`; never edit it directly. Record progress, evidence, findings, decisions, and worker state only through the shared operations.
|
|
12
|
-
- Helpers cannot widen scope, record binding decisions, close or pause the task, assign further helpers, or resolve blockers for the lead.
|
|
13
|
-
- On Cursor, pass the active workspace as `workspace_root` on every repository-scoped call.
|
|
14
|
-
|
|
15
|
-
## Setup
|
|
16
|
-
|
|
17
|
-
1. If there is no active or paused task, call `workit_task` with `action: "start"` then `workit_policy` with `action: "assess"` (CLI: `workit task start …` then `workit policy assess …`).
|
|
18
|
-
2. Load `workit-plan`, list tasks with `workit_task` `action: "list"`, and mirror visible todo state to the host UI.
|
|
19
|
-
3. When policy requires a feature branch, resolve it with read-only `context.read` and apply `git.branch_setup` only after native approval.
|
|
20
|
-
|
|
21
|
-
## Remaining-task loop
|
|
22
|
-
|
|
23
|
-
For each bounded plan task:
|
|
24
|
-
|
|
25
|
-
1. Mark the item in progress in the host todo UI and record boundary progress with `workit_task` `action: "progress"`.
|
|
26
|
-
2. Route by policy: assign bounded workers with `workit_worker` `action: "assign"` when delegation is available; otherwise implement inline. Acquire product-write ownership with `workit_writer` `action: "acquire"` before repository mutations; release it when done.
|
|
27
|
-
3. Record checks and artifacts with `workit_evidence` `action: "record"`. Record review concerns with `workit_finding` `action: "record"`; resolve or defer them with `finding.resolve`. Blocking findings may trigger at most **two** fix+re-review rounds per task; advisory taste/YAGNI items still use `finding.record` and never pause the loop by direct file edit.
|
|
28
|
-
4. Never advance while a foreign writer is active or blocking findings remain open for the current candidate.
|
|
29
|
-
|
|
30
|
-
## Final gate
|
|
31
|
-
|
|
32
|
-
Run repository verification (CLI: `workit doctor`; hosts: approved project verify when policy requires it). **Mandatory:** close the lead task with `workit_task` `action: "close"` (CLI: `workit task close --payload … [--confirm]`) once requirements are satisfied and verification passes — never finish while the task is still `active` or `paused`.
|
|
33
|
-
|
|
34
|
-
## Task order
|
|
35
|
-
|
|
36
|
-
<TASK_LIST>
|
|
37
|
-
|
|
38
|
-
## Quality gate
|
|
39
|
-
|
|
40
|
-
- Specs/plans follow `templates/spec-template.md` / `templates/plan-template.md`.
|