@brainervirus/workit-cli 8.13.1 → 8.14.1
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/dist/index.js +152 -23
- package/package.json +3 -3
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: "8.
|
|
68
|
+
version: "8.14.1",
|
|
69
69
|
private: false,
|
|
70
70
|
description: "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
|
|
71
71
|
keywords: [
|
|
@@ -103,13 +103,13 @@ var init_package = __esm(() => {
|
|
|
103
103
|
},
|
|
104
104
|
dependencies: {
|
|
105
105
|
"@babel/parser": "7.29.9",
|
|
106
|
-
"@brainervirus/workit-cursor": "^8.
|
|
106
|
+
"@brainervirus/workit-cursor": "^8.14.1",
|
|
107
107
|
"@inkjs/ui": "2.0.0",
|
|
108
108
|
ink: "7.1.1",
|
|
109
109
|
react: "19.2.8"
|
|
110
110
|
},
|
|
111
111
|
devDependencies: {
|
|
112
|
-
"@brainervirus/workit-core": "^8.
|
|
112
|
+
"@brainervirus/workit-core": "^8.14.1"
|
|
113
113
|
},
|
|
114
114
|
engines: {
|
|
115
115
|
node: ">=24"
|
|
@@ -7977,6 +7977,16 @@ var init_zod = __esm(() => {
|
|
|
7977
7977
|
|
|
7978
7978
|
// packages/workit-core/src/core/task-contract.ts
|
|
7979
7979
|
import { createHash, randomUUID } from "node:crypto";
|
|
7980
|
+
function resolveIdRef(kind, ref, ids) {
|
|
7981
|
+
if (ids.includes(ref))
|
|
7982
|
+
return success(null, null, ref);
|
|
7983
|
+
const matches = ids.filter((candidate) => candidate.startsWith(ref));
|
|
7984
|
+
if (matches.length === 1)
|
|
7985
|
+
return success(null, null, matches[0]);
|
|
7986
|
+
if (matches.length === 0)
|
|
7987
|
+
return failure2("not_found", `${kind} not found`);
|
|
7988
|
+
return failure2("invalid_input", `${kind} prefix ${ref} is ambiguous; candidates: ${matches.join(", ")}`);
|
|
7989
|
+
}
|
|
7980
7990
|
function parseOperation(family, input) {
|
|
7981
7991
|
if (typeof input === "object" && input !== null && "schemaVersion" in input && input.schemaVersion !== SCHEMA_VERSION)
|
|
7982
7992
|
return failure2("unsupported_version", "unsupported schema version", { operation: family });
|
|
@@ -8079,7 +8089,7 @@ var SCHEMA_VERSION = 1, POLICY_VERSION = "1.0.0", OPERATION_FAMILIES, uuidPatter
|
|
|
8079
8089
|
return true;
|
|
8080
8090
|
}
|
|
8081
8091
|
return false;
|
|
8082
|
-
}, text, id, digest, revision, validUtc = (value) => {
|
|
8092
|
+
}, text, id, idRefPattern, idRef, digest, revision, validUtc = (value) => {
|
|
8083
8093
|
const match = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.(\d{1,9}))?Z$/.exec(value);
|
|
8084
8094
|
if (!match)
|
|
8085
8095
|
return false;
|
|
@@ -8262,6 +8272,8 @@ var init_task_contract = __esm(() => {
|
|
|
8262
8272
|
ctx.issues.push({ code: "custom", input: ctx.value, message: "invalid Unicode", path: [] });
|
|
8263
8273
|
});
|
|
8264
8274
|
id = text.regex(uuidPattern, "expected lowercase UUID");
|
|
8275
|
+
idRefPattern = /^[0-9a-f][0-9a-f-]{7,35}$/;
|
|
8276
|
+
idRef = text.regex(idRefPattern, "expected a UUID or an id prefix of 8+ characters");
|
|
8265
8277
|
digest = text.regex(digestPattern, "expected lowercase SHA-256 digest");
|
|
8266
8278
|
revision = text.regex(uuidPattern, "expected UUID revision");
|
|
8267
8279
|
utcSchema = text.check((ctx) => {
|
|
@@ -8530,7 +8542,7 @@ var init_task_contract = __esm(() => {
|
|
|
8530
8542
|
outcome: _enum(["completed", "failed", "cancelled"]),
|
|
8531
8543
|
summary: text,
|
|
8532
8544
|
evidenceIds: array(id),
|
|
8533
|
-
findingIds: array(
|
|
8545
|
+
findingIds: array(idRef)
|
|
8534
8546
|
}).strict();
|
|
8535
8547
|
workerSchema = object({
|
|
8536
8548
|
assignment: assignmentSchema,
|
|
@@ -8722,7 +8734,7 @@ var init_task_contract = __esm(() => {
|
|
|
8722
8734
|
action: literal("resolve"),
|
|
8723
8735
|
...taskId,
|
|
8724
8736
|
expectedRevision: revision.optional(),
|
|
8725
|
-
findingId:
|
|
8737
|
+
findingId: idRef,
|
|
8726
8738
|
disposition: _enum(["open", "fixed", "dismissed", "deferred"]),
|
|
8727
8739
|
reason: text,
|
|
8728
8740
|
evidenceIds: array(id),
|
|
@@ -8763,7 +8775,7 @@ var init_task_contract = __esm(() => {
|
|
|
8763
8775
|
...taskId,
|
|
8764
8776
|
expectedRevision: revision.optional(),
|
|
8765
8777
|
expectedWorkspaceRevision: revision.optional(),
|
|
8766
|
-
workerId:
|
|
8778
|
+
workerId: idRef,
|
|
8767
8779
|
report: workerReportSchema
|
|
8768
8780
|
}),
|
|
8769
8781
|
cancel: operation({
|
|
@@ -8771,7 +8783,7 @@ var init_task_contract = __esm(() => {
|
|
|
8771
8783
|
...taskId,
|
|
8772
8784
|
...revisions,
|
|
8773
8785
|
expectedWorkspaceRevision: revision.optional(),
|
|
8774
|
-
workerId:
|
|
8786
|
+
workerId: idRef,
|
|
8775
8787
|
reason: text
|
|
8776
8788
|
})
|
|
8777
8789
|
};
|
|
@@ -11453,20 +11465,26 @@ class TaskStore {
|
|
|
11453
11465
|
return success(null, null, { key: key.data, bound: bound.data });
|
|
11454
11466
|
}
|
|
11455
11467
|
taskForWorker(workerId) {
|
|
11456
|
-
if (typeof workerId !== "string" || !
|
|
11468
|
+
if (typeof workerId !== "string" || !idRefPattern.test(workerId))
|
|
11457
11469
|
return failure2("invalid_input", "needs a worker id: `workit worker cancel|report <workerId>`");
|
|
11458
11470
|
const listed = this.listTaskIndex();
|
|
11459
11471
|
if (!listed.ok)
|
|
11460
11472
|
return listed;
|
|
11473
|
+
const owners = new Map;
|
|
11461
11474
|
for (const entry of listed.data) {
|
|
11462
11475
|
if (entry.status === "closed")
|
|
11463
11476
|
continue;
|
|
11464
11477
|
const loaded = this.load(entry.id);
|
|
11465
11478
|
if (!loaded.ok)
|
|
11466
11479
|
return loaded;
|
|
11467
|
-
|
|
11468
|
-
|
|
11480
|
+
for (const worker of loaded.data?.record.workers ?? [])
|
|
11481
|
+
owners.set(worker.id, entry.id);
|
|
11469
11482
|
}
|
|
11483
|
+
const resolved = resolveIdRef("worker", workerId, [...owners.keys()]);
|
|
11484
|
+
if (resolved.ok)
|
|
11485
|
+
return success(null, null, owners.get(resolved.data) ?? null);
|
|
11486
|
+
if (resolved.code !== "not_found")
|
|
11487
|
+
return resolved;
|
|
11470
11488
|
return success(null, null, null);
|
|
11471
11489
|
}
|
|
11472
11490
|
originTaskEntry() {
|
|
@@ -14022,23 +14040,79 @@ var nonBlank, branchPreset, commitPreset, workspaceBranchPolicySchema, workspace
|
|
|
14022
14040
|
}, resolveRuntimeReleaseTracks = (cwd) => {
|
|
14023
14041
|
const matched = matchRuntimeWorkspace(cwd);
|
|
14024
14042
|
return matched ? { workspace: matched.selected.name, releaseTracks: matched.selected.releaseTracks } : null;
|
|
14025
|
-
},
|
|
14043
|
+
}, inheritedSetting = (cwd, dir, has) => {
|
|
14026
14044
|
let matched;
|
|
14027
14045
|
try {
|
|
14028
14046
|
matched = matchRuntimeWorkspace(cwd, dir);
|
|
14029
14047
|
} catch {
|
|
14030
|
-
return
|
|
14048
|
+
return null;
|
|
14031
14049
|
}
|
|
14032
14050
|
if (!matched)
|
|
14033
|
-
return
|
|
14051
|
+
return null;
|
|
14034
14052
|
const { selected, matches } = matched;
|
|
14035
14053
|
const enclosing = matches.filter((entry) => entry !== selected).toSorted((a, b) => globSpecificity(b.glob) - globSpecificity(a.glob));
|
|
14036
|
-
|
|
14054
|
+
return { workspace: selected.name, source: [selected, ...enclosing].find(has) ?? null };
|
|
14055
|
+
}, workspaceTrailers = (cwd, dir) => {
|
|
14056
|
+
const found = inheritedSetting(cwd, dir, (entry) => typeof entry.trailers === "boolean");
|
|
14037
14057
|
return {
|
|
14038
|
-
enabled: source?.trailers !== false,
|
|
14039
|
-
workspace:
|
|
14040
|
-
from: source?.name ?? null
|
|
14058
|
+
enabled: found?.source?.trailers !== false,
|
|
14059
|
+
workspace: found?.workspace ?? null,
|
|
14060
|
+
from: found?.source?.name ?? null
|
|
14041
14061
|
};
|
|
14062
|
+
}, hostFamily = (host) => host.replace(/_(?:cli|desktop)$/u, ""), TIER_KEYS, TIER_HOSTS, workspaceTierModelIssues = (cwd, dir) => {
|
|
14063
|
+
let matched;
|
|
14064
|
+
try {
|
|
14065
|
+
matched = matchRuntimeWorkspace(cwd, dir);
|
|
14066
|
+
} catch {
|
|
14067
|
+
return [];
|
|
14068
|
+
}
|
|
14069
|
+
const issues = [];
|
|
14070
|
+
for (const entry of matched?.matches ?? []) {
|
|
14071
|
+
const models = entry.fanout?.tierModels;
|
|
14072
|
+
if (models === undefined)
|
|
14073
|
+
continue;
|
|
14074
|
+
const where = `workspace ${entry.name} fanout.tierModels`;
|
|
14075
|
+
if (!models || typeof models !== "object" || Array.isArray(models)) {
|
|
14076
|
+
issues.push(`${where} is not an object; ignored`);
|
|
14077
|
+
continue;
|
|
14078
|
+
}
|
|
14079
|
+
for (const [tier, value] of Object.entries(models)) {
|
|
14080
|
+
if (!TIER_KEYS.has(tier))
|
|
14081
|
+
issues.push(`${where}.${tier}: unknown tier; ignored`);
|
|
14082
|
+
else if (typeof value === "string") {
|
|
14083
|
+
if (!value.trim())
|
|
14084
|
+
issues.push(`${where}.${tier}: empty model name; ignored`);
|
|
14085
|
+
} else if (!value || typeof value !== "object" || Array.isArray(value))
|
|
14086
|
+
issues.push(`${where}.${tier}: not a model name or a per-host object; ignored`);
|
|
14087
|
+
else
|
|
14088
|
+
for (const [host, model] of Object.entries(value)) {
|
|
14089
|
+
if (!TIER_HOSTS.has(host))
|
|
14090
|
+
issues.push(`${where}.${tier}.${host}: unknown host; ignored`);
|
|
14091
|
+
else if (typeof model !== "string" || !model.trim())
|
|
14092
|
+
issues.push(`${where}.${tier}.${host}: not a model name; ignored`);
|
|
14093
|
+
}
|
|
14094
|
+
}
|
|
14095
|
+
}
|
|
14096
|
+
return issues;
|
|
14097
|
+
}, workspaceTierModel = (cwd, tier, host, dir) => {
|
|
14098
|
+
const pick = (entry) => {
|
|
14099
|
+
const fanout = entry.fanout;
|
|
14100
|
+
const models = fanout?.tierModels;
|
|
14101
|
+
if (!models || typeof models !== "object" || !Object.hasOwn(models, tier))
|
|
14102
|
+
return null;
|
|
14103
|
+
const value = models[tier];
|
|
14104
|
+
if (typeof value === "string")
|
|
14105
|
+
return value.trim() || null;
|
|
14106
|
+
if (!value || typeof value !== "object")
|
|
14107
|
+
return null;
|
|
14108
|
+
const byHost = value;
|
|
14109
|
+
const family = host ? hostFamily(host) : null;
|
|
14110
|
+
const named = (family && Object.hasOwn(byHost, family) ? byHost[family] : undefined) ?? (host && Object.hasOwn(byHost, host) ? byHost[host] : undefined) ?? (Object.hasOwn(byHost, "default") ? byHost.default : undefined);
|
|
14111
|
+
return typeof named === "string" && named.trim() ? named.trim() : null;
|
|
14112
|
+
};
|
|
14113
|
+
const found = inheritedSetting(cwd, dir, (entry) => pick(entry) !== null);
|
|
14114
|
+
const model = found?.source ? pick(found.source) : null;
|
|
14115
|
+
return model && found?.source ? { model, workspace: found.source.name } : null;
|
|
14042
14116
|
}, resolveRuntimeWorkspaceCandidate = (cwd, kind) => {
|
|
14043
14117
|
const matched = matchRuntimeWorkspace(cwd);
|
|
14044
14118
|
if (!matched)
|
|
@@ -14190,6 +14264,8 @@ var init_workspaces = __esm(() => {
|
|
|
14190
14264
|
defaultEndpoint: unknown().optional(),
|
|
14191
14265
|
verification: _enum(["self", "independent"]).optional(),
|
|
14192
14266
|
trailers: boolean2().optional(),
|
|
14267
|
+
liveSessionGuard: boolean2().optional(),
|
|
14268
|
+
fanout: object({ tierModels: unknown().optional() }).passthrough().optional(),
|
|
14193
14269
|
autonomy: object(Object.fromEntries(["push", "pr", "merge", "release", "rerun"].map((kind) => [
|
|
14194
14270
|
kind,
|
|
14195
14271
|
union([boolean2(), literal("verified")]).optional()
|
|
@@ -14239,6 +14315,17 @@ var init_workspaces = __esm(() => {
|
|
|
14239
14315
|
runtimeWorkspaceIndexSchema = object({
|
|
14240
14316
|
workspaces: array(object({ name: nonBlank, glob: nonBlank }).passthrough()).optional()
|
|
14241
14317
|
}).passthrough();
|
|
14318
|
+
TIER_KEYS = new Set(["mundane", "standard", "hard"]);
|
|
14319
|
+
TIER_HOSTS = new Set([
|
|
14320
|
+
"claude_code",
|
|
14321
|
+
"opencode",
|
|
14322
|
+
"codex",
|
|
14323
|
+
"codex_cli",
|
|
14324
|
+
"codex_desktop",
|
|
14325
|
+
"cursor",
|
|
14326
|
+
"pi",
|
|
14327
|
+
"default"
|
|
14328
|
+
]);
|
|
14242
14329
|
});
|
|
14243
14330
|
|
|
14244
14331
|
// packages/workit-core/src/core/release-tracks.ts
|
|
@@ -18749,6 +18836,10 @@ class WorkitCore {
|
|
|
18749
18836
|
}
|
|
18750
18837
|
if (helper?.ok)
|
|
18751
18838
|
return failure2("permission_denied", "helpers cannot resolve findings");
|
|
18839
|
+
const findingRef = resolveIdRef("finding", input.findingId, task.data.findings.map((entry) => entry.id));
|
|
18840
|
+
if (!findingRef.ok)
|
|
18841
|
+
return findingRef;
|
|
18842
|
+
input.findingId = findingRef.data;
|
|
18752
18843
|
const finding = task.data.findings.find((entry) => entry.id === input.findingId);
|
|
18753
18844
|
if (!finding)
|
|
18754
18845
|
return failure2("not_found", "finding not found");
|
|
@@ -18900,15 +18991,31 @@ class WorkitCore {
|
|
|
18900
18991
|
return changed;
|
|
18901
18992
|
return success(changed.data.task.revision, changed.data.workspace.revision, changed.data.task.workers.at(-1));
|
|
18902
18993
|
}
|
|
18994
|
+
const workerRef = resolveIdRef("worker", input.workerId, helperId === null ? task.data.workers.map((candidate) => candidate.id) : [helperId]);
|
|
18995
|
+
if (!workerRef.ok)
|
|
18996
|
+
return helperId === null ? workerRef : failure2("permission_denied", input.action === "report" ? ONLY_OWN_REPORT : NO_HELPER_CONTROL);
|
|
18997
|
+
input.workerId = workerRef.data;
|
|
18903
18998
|
const entry = task.data.workers.find((candidate) => candidate.id === input.workerId);
|
|
18904
18999
|
if (!entry)
|
|
18905
19000
|
return failure2("not_found", "worker not found");
|
|
18906
19001
|
if (input.action === "report") {
|
|
18907
19002
|
if (helperId === null || helperId !== input.workerId)
|
|
18908
|
-
return failure2("permission_denied",
|
|
19003
|
+
return failure2("permission_denied", ONLY_OWN_REPORT);
|
|
18909
19004
|
const helper = this.helperEntry(task.data, true, true);
|
|
18910
19005
|
if (!helper.ok)
|
|
18911
19006
|
return helper;
|
|
19007
|
+
const ownFindings = task.data.findings.filter((candidate) => candidate.provenance.workerId === helperId).map((candidate) => candidate.id);
|
|
19008
|
+
const reported = [];
|
|
19009
|
+
for (const findingRef of input.report.findingIds) {
|
|
19010
|
+
const found = resolveIdRef("finding", findingRef, ownFindings);
|
|
19011
|
+
if (found.ok)
|
|
19012
|
+
reported.push(found.data);
|
|
19013
|
+
else if (found.code === "not_found")
|
|
19014
|
+
reported.push(findingRef);
|
|
19015
|
+
else
|
|
19016
|
+
return found;
|
|
19017
|
+
}
|
|
19018
|
+
input.report.findingIds = reported;
|
|
18912
19019
|
const evidence = task.data.evidence.filter((candidate) => input.report.evidenceIds.includes(candidate.id));
|
|
18913
19020
|
const findings = task.data.findings.filter((candidate) => input.report.findingIds.includes(candidate.id));
|
|
18914
19021
|
if (evidence.length !== input.report.evidenceIds.length || findings.length !== input.report.findingIds.length)
|
|
@@ -18936,7 +19043,7 @@ class WorkitCore {
|
|
|
18936
19043
|
return updated ? success(changed.data.task.revision, changed.data.workspace.revision, updated) : failure2("recovery_required", "worker disappeared during report");
|
|
18937
19044
|
}
|
|
18938
19045
|
if (helperId !== null)
|
|
18939
|
-
return failure2("permission_denied",
|
|
19046
|
+
return failure2("permission_denied", NO_HELPER_CONTROL);
|
|
18940
19047
|
if (task.data.status === "closed")
|
|
18941
19048
|
return failure2("invalid_transition", "closed task cannot cancel workers");
|
|
18942
19049
|
if (entry.data.state === "stopped") {
|
|
@@ -19465,7 +19572,7 @@ var MAX_JUDGED_REFS = 5, workspaceVerification = (root) => {
|
|
|
19465
19572
|
return changed;
|
|
19466
19573
|
const updated = changed.data.task.workers.find((candidate) => candidate.id === input.workerId);
|
|
19467
19574
|
return updated ? success(changed.data.task.revision, changed.data.workspace.revision, updated) : failure2("recovery_required", "worker disappeared during lifecycle observation");
|
|
19468
|
-
}, refsWithinScope = (refs, scope) => refs.every((ref) => ref.kind !== "file" || scopeCovers(scope, { description: "", paths: [ref.path], exclusions: [] })), TASK_SCOPED_ACTIONS, WORKER_ADDRESSED_ACTIONS, workerCommand = (taskId, request) => {
|
|
19575
|
+
}, refsWithinScope = (refs, scope) => refs.every((ref) => ref.kind !== "file" || scopeCovers(scope, { description: "", paths: [ref.path], exclusions: [] })), TASK_SCOPED_ACTIONS, ONLY_OWN_REPORT = "workers can submit only their own report", NO_HELPER_CONTROL = "helpers cannot cancel or control workers", WORKER_ADDRESSED_ACTIONS, workerCommand = (taskId, request) => {
|
|
19469
19576
|
const { action, workerId, reason, report } = request;
|
|
19470
19577
|
const rest = JSON.stringify({ reason, report });
|
|
19471
19578
|
const payload = rest === "{}" ? "" : ` --payload '${rest.replace(/'/gu, "'\\''")}'`;
|
|
@@ -73303,9 +73410,15 @@ function show(argv, io) {
|
|
|
73303
73410
|
return emit(io, fail("invalid_input", error instanceof Error ? error.message : String(error)));
|
|
73304
73411
|
}
|
|
73305
73412
|
const tracks = releaseTracksReport(io.cwd);
|
|
73306
|
-
const
|
|
73413
|
+
const tierModelIssues = workspaceTierModelIssues(io.cwd);
|
|
73414
|
+
const shown = {
|
|
73415
|
+
...autonomy,
|
|
73416
|
+
...tracks.tracks.length || tracks.error ? { releaseTracks: tracks } : {},
|
|
73417
|
+
...tierModelIssues.length ? { tierModelIssues } : {}
|
|
73418
|
+
};
|
|
73307
73419
|
return emit(io, ok(shown), (data) => [
|
|
73308
73420
|
...data.note ? [`note: ${data.note}`] : [],
|
|
73421
|
+
...tierModelIssues.map((issue) => `note: ${issue}`),
|
|
73309
73422
|
data.workspace ? `workspace ${data.workspace} (${data.source === "default" ? "D4 defaults" : `from ${data.source}`})` : "no workspace matches this checkout: D4 defaults apply",
|
|
73310
73423
|
...describe2(data.grants, data.configured, data, data.verification),
|
|
73311
73424
|
...describeReleaseTracks(tracks).map((line) => ` ${line}`),
|
|
@@ -73401,6 +73514,7 @@ usage: ${USAGE2}`)), run9 = (argv, io) => runGrant(argv, io);
|
|
|
73401
73514
|
var init_grant = __esm(() => {
|
|
73402
73515
|
init_autonomy();
|
|
73403
73516
|
init_release_tracks();
|
|
73517
|
+
init_workspaces();
|
|
73404
73518
|
init_output();
|
|
73405
73519
|
init_prompt();
|
|
73406
73520
|
AGENT_ENV = [
|
|
@@ -82374,6 +82488,7 @@ function renderBrief(cwd, plan, input) {
|
|
|
82374
82488
|
what: String(row.what)
|
|
82375
82489
|
}));
|
|
82376
82490
|
const identity = identityOf(input.actor.host);
|
|
82491
|
+
const model = workspaceTierModel(cwd, slice.tier, input.actor.host);
|
|
82377
82492
|
const minted = workerSession(sessionSafe(input.actor.session), slice.id, input.attempt);
|
|
82378
82493
|
const session = identity === "declared" ? minted : null;
|
|
82379
82494
|
const fanIn = plan.fanIn === "integration" ? [
|
|
@@ -82397,6 +82512,7 @@ function renderBrief(cwd, plan, input) {
|
|
|
82397
82512
|
...slice.acceptance.map((line) => ` - ${line}`),
|
|
82398
82513
|
`VERIFY: ${slice.verify.join("; ")}`,
|
|
82399
82514
|
`TIER: ${slice.tier}`,
|
|
82515
|
+
...model ? [` model: ${model.model} (fanout.tierModels in workspace ${model.workspace})`] : [],
|
|
82400
82516
|
`TIMEBOX: ${slice.timebox ?? DEFAULT_TIMEBOX}; past it without a new commit you will be replaced`,
|
|
82401
82517
|
scratchLine,
|
|
82402
82518
|
`FORBIDDEN: ${slice.forbidden.join("; ")}`,
|
|
@@ -82417,6 +82533,7 @@ function renderBrief(cwd, plan, input) {
|
|
|
82417
82533
|
branch,
|
|
82418
82534
|
base: slice.base,
|
|
82419
82535
|
tier: slice.tier,
|
|
82536
|
+
model: model?.model ?? null,
|
|
82420
82537
|
scratch,
|
|
82421
82538
|
session,
|
|
82422
82539
|
standing,
|
|
@@ -82459,6 +82576,7 @@ var DEFAULT_TIMEBOX = "30 minutes", REPORT, identityOf = (host) => {
|
|
|
82459
82576
|
];
|
|
82460
82577
|
}, sessionSafe = (text) => text.replace(/[^A-Za-z0-9_.:@/+-]/gu, "-"), SESSION_MAX = 128;
|
|
82461
82578
|
var init_fanout_brief = __esm(() => {
|
|
82579
|
+
init_workspaces();
|
|
82462
82580
|
init_ledger();
|
|
82463
82581
|
init_fanout();
|
|
82464
82582
|
init_fanout_worktree();
|
|
@@ -83076,6 +83194,15 @@ function fanoutStatus(cwd, plan, options) {
|
|
|
83076
83194
|
if (row.waitsFor.length && !suggested.includes(id))
|
|
83077
83195
|
row.reasons.push(`waits for ${row.waitsFor.join(", ")}`);
|
|
83078
83196
|
}
|
|
83197
|
+
const host = options.host === undefined ? actorFromEnv(process.env).host : options.host;
|
|
83198
|
+
const spawnModels = {};
|
|
83199
|
+
for (const id of spawnable) {
|
|
83200
|
+
const tier = plan.slices.find((slice) => slice.id === id)?.tier;
|
|
83201
|
+
const model = tier ? workspaceTierModel(cwd, tier, host) : null;
|
|
83202
|
+
if (model)
|
|
83203
|
+
spawnModels[id] = model.model;
|
|
83204
|
+
}
|
|
83205
|
+
const spawnList = spawnable.map((id) => spawnModels[id] ? `${id} (model ${spawnModels[id]})` : id).join(", ");
|
|
83079
83206
|
const stuck = order.filter((id) => out.get(id)?.stuck);
|
|
83080
83207
|
const down = breaker.down();
|
|
83081
83208
|
if (down)
|
|
@@ -83085,7 +83212,7 @@ function fanoutStatus(cwd, plan, options) {
|
|
|
83085
83212
|
const row = out.get(id);
|
|
83086
83213
|
return !row.landed && row.reasons.length === 1 && row.reasons[0] === "no PR";
|
|
83087
83214
|
});
|
|
83088
|
-
const next = stuck.length ? `replace ${stuck.join(", ")}: stop the worker, then workit fanout worktree release ${stuck[0]} (records git status first) and respawn it in MODE: resume` : suggested.length ? online ? `land in this order: ${suggested.join(", ")} (workit fanout check first; workit pr merge each)` : `land in this order: ${suggested.join(", ")} once each has a PR (offline: PRs unchecked; open a missing one with workit git push && workit pr create --fill, then workit fanout status online)` : noPr.length ? `open PRs for ${noPr.join(", ")}: workit git push && workit pr create --fill on each branch` : spawnable.length ? `spawn ${
|
|
83215
|
+
const next = stuck.length ? `replace ${stuck.join(", ")}: stop the worker, then workit fanout worktree release ${stuck[0]} (records git status first) and respawn it in MODE: resume` : suggested.length ? online ? `land in this order: ${suggested.join(", ")} (workit fanout check first; workit pr merge each)` : `land in this order: ${suggested.join(", ")} once each has a PR (offline: PRs unchecked; open a missing one with workit git push && workit pr create --fill, then workit fanout status online)` : noPr.length ? `open PRs for ${noPr.join(", ")}: workit git push && workit pr create --fill on each branch` : spawnable.length ? `spawn ${spawnList} (workit fanout worktree create <slice> on hosts without native worktrees)` : order.every((id) => out.get(id)?.landed) ? "every slice has landed" : "wait for workers, then workit fanout status again";
|
|
83089
83216
|
return {
|
|
83090
83217
|
ok: true,
|
|
83091
83218
|
data: {
|
|
@@ -83099,6 +83226,7 @@ function fanoutStatus(cwd, plan, options) {
|
|
|
83099
83226
|
slices: order.map((id) => out.get(id)),
|
|
83100
83227
|
landingOrder: suggested,
|
|
83101
83228
|
spawnable,
|
|
83229
|
+
spawnModels,
|
|
83102
83230
|
stuck,
|
|
83103
83231
|
next,
|
|
83104
83232
|
notes
|
|
@@ -83112,6 +83240,7 @@ var DEFAULT_STUCK_MS, isoOf = (seconds) => {
|
|
|
83112
83240
|
var init_fanout_status = __esm(() => {
|
|
83113
83241
|
init_duration();
|
|
83114
83242
|
init_report();
|
|
83243
|
+
init_workspaces();
|
|
83115
83244
|
init_ledger();
|
|
83116
83245
|
init_fanout_check();
|
|
83117
83246
|
init_fanout_landed();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainervirus/workit-cli",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.14.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
|
|
6
6
|
"keywords": [
|
|
@@ -38,13 +38,13 @@
|
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@babel/parser": "7.29.9",
|
|
41
|
-
"@brainervirus/workit-cursor": "^8.
|
|
41
|
+
"@brainervirus/workit-cursor": "^8.14.1",
|
|
42
42
|
"@inkjs/ui": "2.0.0",
|
|
43
43
|
"ink": "7.1.1",
|
|
44
44
|
"react": "19.2.8"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"@brainervirus/workit-core": "^8.
|
|
47
|
+
"@brainervirus/workit-core": "^8.14.1"
|
|
48
48
|
},
|
|
49
49
|
"engines": {
|
|
50
50
|
"node": ">=24"
|