@brainervirus/workit-codex 8.9.0 → 8.10.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,6 +1,6 @@
1
1
  {
2
2
  "name": "workit",
3
- "version": "8.9.0",
3
+ "version": "8.10.0",
4
4
  "description": "Adaptive engineering workflow rails for Codex",
5
5
  "author": {
6
6
  "name": "BrainerVirus"
@@ -16061,64 +16061,11 @@ function acquireFileLockSync(targetPath, options) {
16061
16061
  }
16062
16062
  }
16063
16063
  }
16064
- // packages/workit-core/src/host-session.ts
16065
- var HOST_SESSION_VARS = [
16066
- ["OPENCODE_SESSION_ID", () => "opencode"],
16067
- ["PI_SESSION_ID", () => "pi"],
16068
- [
16069
- "CODEX_THREAD_ID",
16070
- (env) => env.CODEX_INTERNAL_ORIGINATOR_OVERRIDE === "Codex Desktop" || env.CODEX_ELECTRON_RESOURCES_PATH ? "codex_desktop" : "codex_cli"
16071
- ]
16072
- ];
16073
- var family = (host) => host?.replace(/_(?:cli|desktop)$/, "") ?? null;
16074
- function hostSessionFromEnv(env) {
16075
- const value = (key) => env[key]?.trim() || null;
16076
- let inner = null;
16077
- for (const [key, host] of HOST_SESSION_VARS) {
16078
- const session = value(key);
16079
- if (session) {
16080
- inner = { host: host(env), session };
16081
- break;
16082
- }
16083
- }
16084
- const declared = value("WORKIT_HOST");
16085
- if (env.WORKIT_SESSION_ID !== undefined) {
16086
- const inherited = inner !== null && declared !== null && family(declared) !== family(inner.host);
16087
- if (!inherited)
16088
- return { host: declared, session: value("WORKIT_SESSION_ID") };
16089
- }
16090
- return inner ? { host: inner.host, session: inner.session } : { host: declared, session: null };
16091
- }
16092
-
16093
- // packages/workit-core/src/core/package-root.ts
16094
- import { existsSync } from "node:fs";
16095
- import path3 from "node:path";
16096
- import { fileURLToPath } from "node:url";
16097
- var packageRoot = () => {
16098
- let dir = path3.dirname(fileURLToPath(import.meta.url));
16099
- while (true) {
16100
- const parent = path3.dirname(dir);
16101
- if (existsSync(path3.join(dir, "package.json")) || parent === dir)
16102
- return dir;
16103
- dir = parent;
16104
- }
16105
- };
16106
- var assetRoot = () => {
16107
- const root = packageRoot();
16108
- const assets = path3.join(root, "assets");
16109
- return existsSync(assets) ? assets : root;
16110
- };
16111
-
16112
- // packages/workit-core/src/core/store-lock.ts
16113
- import { spawnSync as spawnSync2 } from "node:child_process";
16114
- import fs5 from "node:fs";
16115
- import { hostname } from "node:os";
16116
-
16117
16064
  // packages/workit-core/src/store/paths.ts
16118
16065
  import { spawnSync } from "node:child_process";
16119
16066
  import { createHash as createHash2 } from "node:crypto";
16120
16067
  import fs4 from "node:fs";
16121
- import path4 from "node:path";
16068
+ import path3 from "node:path";
16122
16069
  var NOT_A_REPO = /not a git repository \(or any (of the parent directories|parent up to)/u;
16123
16070
  var gitRun = (cwd, args) => {
16124
16071
  const run = spawnSync("git", args, {
@@ -16160,14 +16107,14 @@ var DISCOVERY_ENV = [
16160
16107
  ];
16161
16108
  var isGitDir = (dir) => {
16162
16109
  try {
16163
- return fs4.statSync(path4.join(dir, "HEAD")).isFile() && fs4.statSync(path4.join(dir, "objects")).isDirectory() && fs4.statSync(path4.join(dir, "refs")).isDirectory();
16110
+ return fs4.statSync(path3.join(dir, "HEAD")).isFile() && fs4.statSync(path3.join(dir, "objects")).isDirectory() && fs4.statSync(path3.join(dir, "refs")).isDirectory();
16164
16111
  } catch {
16165
16112
  return false;
16166
16113
  }
16167
16114
  };
16168
16115
  var reftableRefs = (common) => {
16169
16116
  try {
16170
- return /^\s*refstorage\s*=\s*reftable\s*$/imu.test(fs4.readFileSync(path4.join(common, "config"), "utf8"));
16117
+ return /^\s*refstorage\s*=\s*reftable\s*$/imu.test(fs4.readFileSync(path3.join(common, "config"), "utf8"));
16171
16118
  } catch {
16172
16119
  return false;
16173
16120
  }
@@ -16187,7 +16134,7 @@ function fastGit(root) {
16187
16134
  if (device !== null && stat.dev !== device)
16188
16135
  return { kind: "none" };
16189
16136
  device = stat.dev;
16190
- const dotGit = path4.join(dir, ".git");
16137
+ const dotGit = path3.join(dir, ".git");
16191
16138
  let entry = null;
16192
16139
  try {
16193
16140
  entry = fs4.statSync(dotGit);
@@ -16208,19 +16155,19 @@ function fastGit(root) {
16208
16155
  const match = /^gitdir: (.+)$/mu.exec(text);
16209
16156
  if (!match)
16210
16157
  return null;
16211
- gitDir = path4.resolve(dir, match[1].trim());
16158
+ gitDir = path3.resolve(dir, match[1].trim());
16212
16159
  } else
16213
16160
  return null;
16214
- if (!fs4.existsSync(path4.join(gitDir, "HEAD")))
16161
+ if (!fs4.existsSync(path3.join(gitDir, "HEAD")))
16215
16162
  return null;
16216
16163
  } else if (isGitDir(dir))
16217
16164
  gitDir = dir;
16218
16165
  if (gitDir) {
16219
16166
  let common = gitDir;
16220
16167
  try {
16221
- common = path4.resolve(gitDir, fs4.readFileSync(path4.join(gitDir, "commondir"), "utf8").trim());
16168
+ common = path3.resolve(gitDir, fs4.readFileSync(path3.join(gitDir, "commondir"), "utf8").trim());
16222
16169
  } catch {}
16223
- if (!fs4.existsSync(path4.join(common, "objects")))
16170
+ if (!fs4.existsSync(path3.join(common, "objects")))
16224
16171
  return null;
16225
16172
  return {
16226
16173
  kind: "repo",
@@ -16230,26 +16177,26 @@ function fastGit(root) {
16230
16177
  reftable: reftableRefs(common)
16231
16178
  };
16232
16179
  }
16233
- const parent = path4.dirname(dir);
16180
+ const parent = path3.dirname(dir);
16234
16181
  if (parent === dir)
16235
16182
  return { kind: "none" };
16236
16183
  dir = parent;
16237
16184
  }
16238
16185
  }
16239
16186
  function resolveStore(root) {
16240
- root = path4.resolve(root);
16187
+ root = path3.resolve(root);
16241
16188
  let directory = false;
16242
16189
  try {
16243
16190
  directory = fs4.statSync(root).isDirectory();
16244
16191
  } catch {}
16245
16192
  if (!directory)
16246
- return { dir: path4.join(root, ".workit"), shared: false, top: null };
16193
+ return { dir: path3.join(root, ".workit"), shared: false, top: null };
16247
16194
  const fast = fastGit(root);
16248
16195
  if (fast?.kind === "none")
16249
- return { dir: path4.join(root, ".workit"), shared: false, top: null };
16196
+ return { dir: path3.join(root, ".workit"), shared: false, top: null };
16250
16197
  if (fast?.kind === "repo")
16251
16198
  return {
16252
- dir: path4.join(fast.common, "workit"),
16199
+ dir: path3.join(fast.common, "workit"),
16253
16200
  shared: true,
16254
16201
  top: fast.top,
16255
16202
  git: { gitDir: fast.gitDir, top: fast.top, reftable: fast.reftable }
@@ -16259,20 +16206,20 @@ function resolveStore(root) {
16259
16206
  if (run.ok && common) {
16260
16207
  const top = gitRun(root, ["rev-parse", "--path-format=absolute", "--show-toplevel"]);
16261
16208
  return {
16262
- dir: path4.join(real(path4.resolve(root, common)), "workit"),
16209
+ dir: path3.join(real(path3.resolve(root, common)), "workit"),
16263
16210
  shared: true,
16264
16211
  top: top.ok && top.stdout.trim() ? real(top.stdout.trim()) : null
16265
16212
  };
16266
16213
  }
16267
16214
  if (run.missing || !run.ok && NOT_A_REPO.test(run.stderr))
16268
- return { dir: path4.join(root, ".workit"), shared: false, top: null };
16215
+ return { dir: path3.join(root, ".workit"), shared: false, top: null };
16269
16216
  return new Error(`cannot locate the workit store: git rev-parse failed (${run.stderr.trim().split(`
16270
16217
  `)[0] || "no output"}); fix the repository (git status should work here)`);
16271
16218
  }
16272
16219
  var rebasingBranch = (gitDir) => {
16273
16220
  for (const state of ["rebase-merge", "rebase-apply"]) {
16274
16221
  try {
16275
- const ref = fs4.readFileSync(path4.join(gitDir, state, "head-name"), "utf8").trim();
16222
+ const ref = fs4.readFileSync(path3.join(gitDir, state, "head-name"), "utf8").trim();
16276
16223
  const match = /^refs\/heads\/(.+)$/u.exec(ref);
16277
16224
  if (match)
16278
16225
  return match[1];
@@ -16287,7 +16234,7 @@ function resolveTaskKey(root, location) {
16287
16234
  if (location.git && !location.git.reftable) {
16288
16235
  let head = "";
16289
16236
  try {
16290
- head = fs4.readFileSync(path4.join(location.git.gitDir, "HEAD"), "utf8").trim();
16237
+ head = fs4.readFileSync(path3.join(location.git.gitDir, "HEAD"), "utf8").trim();
16291
16238
  } catch {}
16292
16239
  const ref = /^ref: refs\/heads\/(.+)$/u.exec(head);
16293
16240
  if (ref && ref[1] !== ".invalid")
@@ -16318,7 +16265,7 @@ function resolveTaskKey(root, location) {
16318
16265
  return { key: `detached-${shortHash(real(worktree))}`, kind: "detached", branch: null };
16319
16266
  }
16320
16267
  function checkoutRootOf(root, location) {
16321
- const resolved = path4.resolve(root);
16268
+ const resolved = path3.resolve(root);
16322
16269
  let canonical = resolved;
16323
16270
  try {
16324
16271
  canonical = fs4.realpathSync(resolved);
@@ -16349,13 +16296,13 @@ function branchRenames(location) {
16349
16296
  }
16350
16297
  for (const entry of entries)
16351
16298
  if (entry.isDirectory())
16352
- walk(path4.join(dir, entry.name));
16299
+ walk(path3.join(dir, entry.name));
16353
16300
  else
16354
- files.push(path4.join(dir, entry.name));
16301
+ files.push(path3.join(dir, entry.name));
16355
16302
  };
16356
- walk(path4.join(path4.dirname(location.dir), "logs", "refs", "heads"));
16303
+ walk(path3.join(path3.dirname(location.dir), "logs", "refs", "heads"));
16357
16304
  if (location.git)
16358
- files.push(path4.join(location.git.gitDir, "logs", "HEAD"));
16305
+ files.push(path3.join(location.git.gitDir, "logs", "HEAD"));
16359
16306
  const seen = new Set;
16360
16307
  const renames = [];
16361
16308
  for (const file of files) {
@@ -16390,11 +16337,63 @@ var checkoutSlug = (root) => {
16390
16337
  let canonical = real(root);
16391
16338
  if (process.platform === "win32")
16392
16339
  canonical = canonical.toLowerCase();
16393
- const base = path4.basename(canonical).replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 40) || "root";
16340
+ const base = path3.basename(canonical).replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 40) || "root";
16394
16341
  return `${base}-${shortHash(canonical)}`;
16395
16342
  };
16396
16343
 
16344
+ // packages/workit-core/src/host-session.ts
16345
+ var HOST_SESSION_VARS = [
16346
+ ["OPENCODE_SESSION_ID", () => "opencode"],
16347
+ ["PI_SESSION_ID", () => "pi"],
16348
+ [
16349
+ "CODEX_THREAD_ID",
16350
+ (env) => env.CODEX_INTERNAL_ORIGINATOR_OVERRIDE === "Codex Desktop" || env.CODEX_ELECTRON_RESOURCES_PATH ? "codex_desktop" : "codex_cli"
16351
+ ]
16352
+ ];
16353
+ var family = (host) => host?.replace(/_(?:cli|desktop)$/, "") ?? null;
16354
+ function hostSessionFromEnv(env) {
16355
+ const value = (key) => env[key]?.trim() || null;
16356
+ let inner = null;
16357
+ for (const [key, host] of HOST_SESSION_VARS) {
16358
+ const session = value(key);
16359
+ if (session) {
16360
+ inner = { host: host(env), session };
16361
+ break;
16362
+ }
16363
+ }
16364
+ const declared = value("WORKIT_HOST");
16365
+ if (env.WORKIT_SESSION_ID !== undefined) {
16366
+ const inherited = inner !== null && declared !== null && family(declared) !== family(inner.host);
16367
+ if (!inherited)
16368
+ return { host: declared, session: value("WORKIT_SESSION_ID") };
16369
+ }
16370
+ return inner ? { host: inner.host, session: inner.session } : { host: declared, session: null };
16371
+ }
16372
+ var OWN_CHILD_SHELL = new Set(["opencode", "pi"]);
16373
+
16374
+ // packages/workit-core/src/core/package-root.ts
16375
+ import { existsSync } from "node:fs";
16376
+ import path4 from "node:path";
16377
+ import { fileURLToPath } from "node:url";
16378
+ var packageRoot = () => {
16379
+ let dir = path4.dirname(fileURLToPath(import.meta.url));
16380
+ while (true) {
16381
+ const parent = path4.dirname(dir);
16382
+ if (existsSync(path4.join(dir, "package.json")) || parent === dir)
16383
+ return dir;
16384
+ dir = parent;
16385
+ }
16386
+ };
16387
+ var assetRoot = () => {
16388
+ const root = packageRoot();
16389
+ const assets = path4.join(root, "assets");
16390
+ return existsSync(assets) ? assets : root;
16391
+ };
16392
+
16397
16393
  // packages/workit-core/src/core/store-lock.ts
16394
+ import { spawnSync as spawnSync2 } from "node:child_process";
16395
+ import fs5 from "node:fs";
16396
+ import { hostname } from "node:os";
16398
16397
  var metadataLockSchema = object({
16399
16398
  pid: number2().int().nonnegative().safe(),
16400
16399
  processStart: string2().nullable(),
@@ -17028,6 +17027,38 @@ var isNewerVersion = (candidate, current) => {
17028
17027
  return false;
17029
17028
  };
17030
17029
  var validId = (value) => /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(value);
17030
+ var readText = (file) => {
17031
+ try {
17032
+ return fs7.readFileSync(file, "utf8");
17033
+ } catch {
17034
+ return "";
17035
+ }
17036
+ };
17037
+ var REFLOG_LINE = /^[0-9a-f]+ ([0-9a-f]+) .* (\d+) [+-]\d{4}\t(.*)$/u;
17038
+ var branchStart = (location, branch, aliases) => {
17039
+ const first = readText(path6.join(path6.dirname(location.dir), "logs", "refs", "heads", branch)).split(`
17040
+ `, 1)[0];
17041
+ const created = REFLOG_LINE.exec(first);
17042
+ const start = created && /^branch: Created from (\S+)$/u.exec(created[3])?.[1];
17043
+ if (!created || !start)
17044
+ return null;
17045
+ if (start !== "HEAD")
17046
+ return start;
17047
+ if (!location.git)
17048
+ return null;
17049
+ for (const line of readText(path6.join(location.git.gitDir, "logs", "HEAD")).split(`
17050
+ `)) {
17051
+ const entry = REFLOG_LINE.exec(line);
17052
+ const moved = entry && /^checkout: moving from (\S+) to (\S+)$/u.exec(entry[3]);
17053
+ const seconds = entry ? Number(entry[2]) - Number(created[2]) : -1;
17054
+ if (moved && entry[1] === created[1] && seconds >= 0 && seconds <= 1 && aliases.includes(moved[2]))
17055
+ return moved[1];
17056
+ }
17057
+ return null;
17058
+ };
17059
+ var refExists = (common, ref) => fs7.existsSync(path6.join(common, ref)) || readText(path6.join(common, "packed-refs")).includes(` ${ref}
17060
+ `);
17061
+ var origins = new Map;
17031
17062
  var sameDirectoryIdentity = (left, right) => {
17032
17063
  if (!path6.isAbsolute(left) || !path6.isAbsolute(right))
17033
17064
  return false;
@@ -17280,6 +17311,66 @@ class TaskStore {
17280
17311
  return bound;
17281
17312
  return success(null, null, { key: key.data, bound: bound.data });
17282
17313
  }
17314
+ taskForWorker(workerId) {
17315
+ if (typeof workerId !== "string" || !validId(workerId))
17316
+ return failure2("invalid_input", "needs a worker id: `workit worker cancel|report <workerId>`");
17317
+ const listed = this.listTaskIndex();
17318
+ if (!listed.ok)
17319
+ return listed;
17320
+ for (const entry of listed.data) {
17321
+ if (entry.status === "closed")
17322
+ continue;
17323
+ const loaded = this.load(entry.id);
17324
+ if (!loaded.ok)
17325
+ return loaded;
17326
+ if (loaded.data?.record.workers.some((worker) => worker.id === workerId))
17327
+ return success(null, null, entry.id);
17328
+ }
17329
+ return success(null, null, null);
17330
+ }
17331
+ originTaskEntry() {
17332
+ const key = this.currentKey();
17333
+ const location = this.location();
17334
+ const branch = key.ok ? key.data.branch : null;
17335
+ if (!branch || !location.ok)
17336
+ return success(null, null, null);
17337
+ const common = path6.dirname(location.data.dir);
17338
+ const heads = path6.join(common, "logs", "refs", "heads");
17339
+ const headLog = location.data.git ? path6.join(location.data.git.gitDir, "logs", "HEAD") : "";
17340
+ const signatures = [
17341
+ path6.join(heads, branch),
17342
+ headLog,
17343
+ heads,
17344
+ path6.join(common, "packed-refs")
17345
+ ].map((file) => fileSignature(file) ?? "-");
17346
+ const slot = `${location.data.dir}\x00${headLog}\x00${branch}`;
17347
+ let resolved = origins.get(slot);
17348
+ if (resolved?.signature !== signatures.join("|")) {
17349
+ const renames = branchRenames(location.data);
17350
+ const aliases = [branch];
17351
+ for (const rename of renames.toReversed())
17352
+ if (rename.to === aliases.at(-1))
17353
+ aliases.push(rename.from);
17354
+ const start = branchStart(location.data, branch, aliases);
17355
+ const slash = start?.indexOf("/") ?? -1;
17356
+ const remote = slash > 0 && !refExists(common, `refs/heads/${start}`) && (refExists(common, `refs/remotes/${start}`) || readText(path6.join(common, "config")).includes(`[remote "${start.slice(0, slash)}"]`));
17357
+ const name = start && (remote ? start.slice(slash + 1) : start);
17358
+ resolved = {
17359
+ signature: signatures.join("|"),
17360
+ name: name && !aliases.includes(name) ? name : null,
17361
+ renames
17362
+ };
17363
+ origins.set(slot, resolved);
17364
+ }
17365
+ const entry = resolved.name ? this.openTasksForKey(resolved.name, resolved.renames) : null;
17366
+ if (entry && !entry.ok)
17367
+ return entry;
17368
+ return success(null, null, entry?.data[0] ? { origin: `branch ${resolved.name}`, entry: entry.data[0] } : null);
17369
+ }
17370
+ readStoreTask(taskId) {
17371
+ const loaded = this.load(taskId);
17372
+ return loaded.ok ? success(null, null, loaded.data?.record ?? null) : loaded;
17373
+ }
17283
17374
  create(input, provenance, expectedWorkspaceRevision) {
17284
17375
  const value = "intent" in input ? input : {
17285
17376
  intent: input,
@@ -17949,12 +18040,12 @@ class TaskStore {
17949
18040
  return 0;
17950
18041
  }
17951
18042
  }
17952
- openTasksForKey(key) {
18043
+ openTasksForKey(key, known) {
17953
18044
  const all = this.listStoreIndex();
17954
18045
  if (!all.ok)
17955
18046
  return all;
17956
- const location = this.location();
17957
- const renames = location.ok ? branchRenames(location.data) : [];
18047
+ const location = known ? null : this.location();
18048
+ const renames = known ?? (location?.ok ? branchRenames(location.data) : []);
17958
18049
  return success(null, null, all.data.filter((entry) => entry.key !== null && entry.status !== "closed").filter((entry) => (renames.length ? followRenames(entry.key, entry.boundAt ?? entry.createdAt, renames) : entry.key) === key).toSorted(oldestFirst));
17959
18050
  }
17960
18051
  openTaskForKey(key) {
@@ -20935,11 +21026,20 @@ function authorSessions(cwd, rows, branch, range = { base: null, head: null }, s
20935
21026
  sessions.add(session);
20936
21027
  return sessions;
20937
21028
  }
21029
+ var derivesFrom = (derived, bare) => !bare.includes(":") && derived.endsWith(`:${bare}`);
21030
+ var authoredBy = (authors, session) => {
21031
+ if (authors.has(session))
21032
+ return true;
21033
+ for (const author of authors)
21034
+ if (derivesFrom(author, session) || derivesFrom(session, author))
21035
+ return true;
21036
+ return false;
21037
+ };
20938
21038
  var independenceReasons = (row, authors) => {
20939
21039
  const reasons = [];
20940
21040
  if (!row.actor.session)
20941
21041
  reasons.push("no_session");
20942
- else if (authors.has(row.actor.session))
21042
+ else if (authoredBy(authors, row.actor.session))
20943
21043
  reasons.push("author_session");
20944
21044
  if (row.self === true && !reasons.includes("no_session"))
20945
21045
  reasons.push("self");
@@ -22040,38 +22140,45 @@ var compactReference = (ref) => {
22040
22140
  };
22041
22141
  return { kind: ref.kind };
22042
22142
  };
22043
- function compactTaskContext(view) {
22044
- const decisions = view.task.decisions.slice().toSorted((left, right) => {
22045
- const leftAt = compactTimestamp(left.recordedAt);
22046
- const rightAt = compactTimestamp(right.recordedAt);
22047
- if (leftAt !== rightAt)
22048
- return leftAt > rightAt ? -1 : 1;
22049
- return left.id < right.id ? -1 : left.id > right.id ? 1 : 0;
22050
- }).slice(0, COMPACT_MAX_ITEMS).map((entry) => ({
22051
- id: entry.id,
22052
- purpose: entry.data.purpose,
22053
- status: entry.data.response,
22054
- digest: entry.data.digest,
22055
- choice: compactDecisionChoice(entry) || `task.inspect taskId=${view.task.id} view=full; decision=${entry.id}`,
22056
- references: entry.data.binding.contentRefs.slice(0, 1).map(compactReference)
22057
- }));
22058
- const methods = view.task.policy ? selectMethods(view.task.policy, view.capabilities).map((method) => ({
22143
+ var newestDecisionFirst = (left, right) => {
22144
+ const leftAt = compactTimestamp(left.recordedAt);
22145
+ const rightAt = compactTimestamp(right.recordedAt);
22146
+ if (leftAt !== rightAt)
22147
+ return leftAt > rightAt ? -1 : 1;
22148
+ return left.id < right.id ? -1 : left.id > right.id ? 1 : 0;
22149
+ };
22150
+ var compactDecisions = (sources) => sources.flatMap((source) => source ? source.decisions.toSorted(newestDecisionFirst).map((entry) => ({
22151
+ id: entry.id,
22152
+ purpose: entry.data.purpose,
22153
+ status: entry.data.response,
22154
+ digest: entry.data.digest,
22155
+ choice: compactDecisionChoice(entry) || `task.inspect taskId=${source.taskId} view=full; decision=${entry.id}`,
22156
+ references: entry.data.binding.contentRefs.slice(0, 1).map(compactReference),
22157
+ origin: source.origin ?? undefined
22158
+ })) : []).slice(0, COMPACT_MAX_ITEMS);
22159
+ function compactTaskContext(view, inherited = null) {
22160
+ const decisions = compactDecisions([
22161
+ view && { origin: null, taskId: view.task.id, decisions: view.task.decisions },
22162
+ inherited
22163
+ ]);
22164
+ const methods = view?.task.policy ? selectMethods(view.task.policy, view.capabilities).map((method) => ({
22059
22165
  id: method.id,
22060
22166
  assurance: method.assurance,
22061
22167
  reason: compactText(method.reason, COMPACT_TEXT_BYTES) ?? ""
22062
22168
  })) : [];
22169
+ const stale = view?.evidence.filter((entry) => entry.status === "stale").length;
22063
22170
  const gaps = Array.from(new Set([
22064
- ...view.evidence.filter((entry) => entry.status === "stale").map((entry) => `stale evidence: ${entry.evidenceId}`),
22065
- ...view.requirements.filter((entry) => entry.status !== "satisfied").map((entry) => entry.reason),
22066
- ...view.task.progress.blockers.map((entry) => entry.reason)
22171
+ ...stale ? [`stale evidence: ${stale}; workit task inspect --task ${view.task.id} --view full`] : [],
22172
+ ...(view?.requirements ?? []).filter((entry) => entry.status !== "satisfied").map((entry) => entry.reason),
22173
+ ...(view?.task.progress.blockers ?? []).map((entry) => entry.reason)
22067
22174
  ])).toSorted().slice(0, COMPACT_MAX_ITEMS).map((gap) => compactText(gap, COMPACT_TEXT_BYTES));
22068
22175
  const context = {
22069
- objective: compactText(view.task.intent.data.objective, COMPACT_TEXT_BYTES) ?? "",
22070
- status: view.task.status,
22176
+ objective: view ? compactText(view.task.intent.data.objective, COMPACT_TEXT_BYTES) ?? "" : "no task on this branch yet",
22177
+ status: view?.task.status ?? null,
22071
22178
  decisions,
22072
22179
  methods,
22073
22180
  gaps,
22074
- nextAction: compactText(view.task.progress.nextAction, COMPACT_TEXT_BYTES)
22181
+ nextAction: compactText(view?.task.progress.nextAction ?? null, COMPACT_TEXT_BYTES)
22075
22182
  };
22076
22183
  let encoded = JSON.stringify(context);
22077
22184
  while (compactBytes(encoded) > COMPACT_MAX_BYTES && (context.decisions.length || context.methods.length || context.gaps.length)) {
@@ -22676,6 +22783,13 @@ var TASK_SCOPED_ACTIONS = new Set([
22676
22783
  "worker.cancel",
22677
22784
  "state.export"
22678
22785
  ]);
22786
+ var WORKER_ADDRESSED_ACTIONS = new Set(["worker.cancel", "worker.report"]);
22787
+ var workerCommand = (taskId, request) => {
22788
+ const { action, workerId, reason, report } = request;
22789
+ const rest = JSON.stringify({ reason, report });
22790
+ const payload = rest === "{}" ? "" : ` --payload '${rest.replace(/'/gu, "'\\''")}'`;
22791
+ return `workit worker ${String(action)} ${String(workerId)} --task ${taskId}${payload}`;
22792
+ };
22679
22793
  var CREATING_ACTIONS = new Set([
22680
22794
  "task.revise",
22681
22795
  "task.progress",
@@ -22926,6 +23040,17 @@ class WorkitCore {
22926
23040
  const root = this.contextRootError();
22927
23041
  if (!root.ok)
22928
23042
  return root;
23043
+ const addressed = WORKER_ADDRESSED_ACTIONS.has(action);
23044
+ const workerId = addressed ? value.workerId : this.context.workerId ?? null;
23045
+ if (workerId !== null) {
23046
+ const owner = this.store.taskForWorker(workerId);
23047
+ if (!owner.ok)
23048
+ return owner;
23049
+ if (owner.data)
23050
+ return success(null, null, { ...request, taskId: owner.data });
23051
+ if (addressed)
23052
+ return failure2("not_found", `worker ${workerId} is on no open task; find its task with \`workit task status --all\`, then run \`${workerCommand("<task-id>", request)}\``);
23053
+ }
22929
23054
  const create = CREATING_ACTIONS.has(action) && (this.context.workerId ?? null) === null;
22930
23055
  const found = this.store.implicitTask({
22931
23056
  provenance: provenance(this.context),
@@ -23632,7 +23757,9 @@ class WorkitCore {
23632
23757
  if (!resolved.ok)
23633
23758
  return resolved;
23634
23759
  const value = resolved.data;
23635
- return this.retryOmittedRevisions(value, () => this.workerOnce(value));
23760
+ const result = this.retryOmittedRevisions(value, () => this.workerOnce(value));
23761
+ const { action, taskId } = value ?? {};
23762
+ return result.ok || request?.taskId !== undefined || typeof taskId !== "string" || !WORKER_ADDRESSED_ACTIONS.has(`worker.${String(action)}`) ? result : { ...result, error: `${result.error}; run \`${workerCommand(taskId, value)}\`` };
23636
23763
  }
23637
23764
  workerOnce(request) {
23638
23765
  const root = this.contextRootError();
@@ -23837,10 +23964,18 @@ class WorkitCore {
23837
23964
  requirements
23838
23965
  });
23839
23966
  }
23840
- compactContext(taskId, freshness) {
23967
+ compactContext(taskId, freshness, origin = null) {
23841
23968
  const root = this.contextRootError();
23842
23969
  if (!root.ok)
23843
23970
  return root;
23971
+ const base = origin && this.store.readStoreTask(origin.taskId);
23972
+ const inherited = base?.ok && base.data ? {
23973
+ origin: origin.origin,
23974
+ taskId: base.data.id,
23975
+ decisions: base.data.decisions.filter((entry) => entry.data.revoked === null)
23976
+ } : null;
23977
+ if (taskId === null)
23978
+ return success(null, null, inherited?.decisions.length ? compactTaskContext(null, inherited) : "");
23844
23979
  const task = this.store.readTask(taskId);
23845
23980
  if (!task.ok)
23846
23981
  return task;
@@ -23850,7 +23985,7 @@ class WorkitCore {
23850
23985
  const view = this.view(task.data, false, freshness ?? signalFreshness(this.store.root));
23851
23986
  if (!view.ok)
23852
23987
  return view;
23853
- return success(view.revision, view.workspaceRevision, compactTaskContext(view.data));
23988
+ return success(view.revision, view.workspaceRevision, compactTaskContext(view.data, inherited));
23854
23989
  }
23855
23990
  view(task, capture = true, freshness = treeFreshness(this.store.root)) {
23856
23991
  const workspace = this.store.readWorkspace();