@brainervirus/workit-codex 1.1.1 → 1.2.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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "workit",
3
- "version": "1.1.1",
3
+ "version": "1.2.1",
4
4
  "description": "Adaptive engineering workflow rails for Codex",
5
5
  "author": {
6
6
  "name": "BrainerVirus"
@@ -14551,6 +14551,7 @@ var workerSchema = object({
14551
14551
  assignment: assignmentSchema,
14552
14552
  state: _enum(["assigned", "dispatching", "running", "cancelling", "stopped", "unknown"]),
14553
14553
  session: refSchema.nullable(),
14554
+ coordinator: refSchema.optional(),
14554
14555
  report: workerReportSchema.nullable()
14555
14556
  }).strict();
14556
14557
  var ownerSchema = object({
@@ -14662,6 +14663,7 @@ var taskSummarySchema = object({
14662
14663
  requirements: array(requirementEvaluationSchema),
14663
14664
  writer: workspaceRecordSchema.shape.writer
14664
14665
  }).strict();
14666
+ var taskListItemSchema = taskSummarySchema.omit({ policy: true, requirements: true });
14665
14667
  var exportBundleSchema = object({
14666
14668
  schemaVersion: literal(1),
14667
14669
  exportedAt: utc,
@@ -14683,11 +14685,15 @@ var taskOperations = {
14683
14685
  expectedWorkspaceRevision: revision.nullable().optional(),
14684
14686
  intent: intentSchema
14685
14687
  }),
14686
- list: operation({ action: literal("list") }),
14688
+ list: operation({
14689
+ action: literal("list"),
14690
+ status: _enum(["open", "closed", "all"]).optional(),
14691
+ limit: number2().int().min(1).max(50).optional()
14692
+ }),
14687
14693
  inspect: operation({
14688
14694
  action: literal("inspect"),
14689
14695
  ...taskId,
14690
- view: _enum(["summary", "full"])
14696
+ view: _enum(["summary", "full"]).optional()
14691
14697
  }),
14692
14698
  revise: operation({
14693
14699
  action: literal("revise"),
@@ -14715,7 +14721,7 @@ var taskOperations = {
14715
14721
  ...taskId,
14716
14722
  ...revisions,
14717
14723
  expectedWorkspaceRevision: revision.optional(),
14718
- authorityRefs: array(refSchema)
14724
+ authorityRefs: array(refSchema).optional()
14719
14725
  }),
14720
14726
  close: operation({
14721
14727
  action: literal("close"),
@@ -16548,6 +16554,10 @@ var validPath = (value) => typeof value === "string" && value.length > 0 && ![..
16548
16554
  }) && !value.split(/[\\/]/).includes("..");
16549
16555
  var callerValue = (value) => ({ host: value.host, actor: value.actor });
16550
16556
  var workerIdOf = (value) => value.workerId ?? null;
16557
+ var currentWriterOwnsTask = (task, workspace, caller) => {
16558
+ const owner = workspace.writer?.owner;
16559
+ return task.status === "active" && task.workspaceId === workspace.id && owner?.taskId === task.id && owner.session.host === caller.host && owner.session.handle === caller.actor;
16560
+ };
16551
16561
  function assertProductWriteAllowed(input) {
16552
16562
  if (!Array.isArray(input.paths) || input.paths.some((path) => !validPath(path)))
16553
16563
  return failure("invalid_input", "invalid product write path");
@@ -17264,9 +17274,11 @@ var standingReceiptFor = (root, workspace, cls, dir) => {
17264
17274
  var verifyStandingApproval = (root, task, caller, binding) => {
17265
17275
  if (task.status !== "active")
17266
17276
  return failure("invalid_transition", "only active tasks can authorize actions");
17267
- const session = task.intent?.provenance?.session;
17268
- if (!session || session.kind !== "host" || session.host !== caller.host || session.handle !== caller.actor)
17269
- return failure("permission_denied", "standing approval requires the lead session");
17277
+ const workspace = new TaskStore(root).readWorkspace();
17278
+ if (!workspace.ok)
17279
+ return workspace;
17280
+ if (!workspace.data || !currentWriterOwnsTask(task, workspace.data, caller))
17281
+ return failure("permission_denied", "standing approval requires the current writer session");
17270
17282
  const standing = binding.standing;
17271
17283
  if (!standing || typeof standing.workspace !== "string" || typeof standing.class !== "string")
17272
17284
  return failure("invalid_input", "standing approval needs a workspace and class");
@@ -17503,6 +17515,20 @@ var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
17503
17515
  };
17504
17516
  var verifyContentRefs = (store, binding) => verifyDecisionContentAtRoot(store.root, binding);
17505
17517
  var storedDecisionApplicable = (store, task, purpose, binding) => task.decisions.filter((entry) => entry.provenance.kind !== "imported" && decisionMatches(entry, purpose, binding) && verifyDecisionContentAtRoot(store.root, entry.data.binding).ok);
17518
+ var approvalAuthorityMatches = (store, task, approval, current) => {
17519
+ if (approval.kind !== "host_observed" || approval.receipts.length === 0)
17520
+ return false;
17521
+ if (provenanceMatches(approval, current))
17522
+ return true;
17523
+ const session = current.kind === "host_observed" ? current.session : null;
17524
+ if (!session || session.kind !== "host")
17525
+ return false;
17526
+ const workspace = store.readWorkspace();
17527
+ return workspace.ok && workspace.data !== null && currentWriterOwnsTask(task, workspace.data, {
17528
+ host: session.host,
17529
+ actor: session.handle
17530
+ });
17531
+ };
17506
17532
  var validateAction = (store, task, workspaceId, input, authority) => {
17507
17533
  if (task.status !== "active")
17508
17534
  return failure("invalid_transition", "only active tasks can authorize actions");
@@ -17528,7 +17554,7 @@ var validateAction = (store, task, workspaceId, input, authority) => {
17528
17554
  return failure("permission_denied", "native reservation authority does not match decision");
17529
17555
  if (decision.response !== "approved")
17530
17556
  return failure("permission_denied", "decision was rejected");
17531
- if (entry.provenance.kind !== "host_observed" || entry.provenance.receipts.length === 0 || !provenanceMatches(entry.provenance, authority.provenance))
17557
+ if (!approvalAuthorityMatches(store, task, entry.provenance, authority.provenance))
17532
17558
  return failure("permission_denied", "action approval lacks native receipt assurance");
17533
17559
  const receipts = entry.provenance.receipts;
17534
17560
  const standing = receipts.filter((receipt) => typeof receipt === "object" && receipt !== null && receipt.kind === "standing");
@@ -17695,7 +17721,7 @@ function settleAction(input) {
17695
17721
  return failure("not_found", "decision not found");
17696
17722
  if (!authorityDecisionMatches(authority, entry.data))
17697
17723
  return failure("permission_denied", "native settlement authority does not match decision");
17698
- if (!provenanceMatches(entry.provenance, authority.provenance))
17724
+ if (!approvalAuthorityMatches(input.store, current, entry.provenance, authority.provenance))
17699
17725
  return failure("permission_denied", "native settlement caller does not match approval");
17700
17726
  if (entry.data.purpose !== "action" || entry.data.digest !== decisionDigest(entry.data))
17701
17727
  return failure("permission_denied", "decision binding is invalid");
@@ -17794,7 +17820,7 @@ function reconcileAction(input) {
17794
17820
  const entry = current.decisions.find((candidate) => candidate.id === input.decisionId);
17795
17821
  if (!entry || entry.data.purpose !== "action")
17796
17822
  return failure("not_found", "decision not found");
17797
- if (!authorityDecisionMatches(authority, entry.data) || !provenanceMatches(entry.provenance, authority.provenance))
17823
+ if (!authorityDecisionMatches(authority, entry.data) || !approvalAuthorityMatches(input.store, current, entry.provenance, authority.provenance))
17798
17824
  return failure("permission_denied", "native reconciliation caller does not match approval");
17799
17825
  if (entry.data.response !== "approved" || entry.data.revoked !== null || entry.data.digest !== decisionDigest(entry.data) || entry.data.binding.taskId !== current.id || entry.data.binding.workspaceId !== current.workspaceId || entry.data.binding.workspaceId !== workspace.data.id)
17800
17826
  return failure("permission_denied", "reconciliation decision binding is invalid");
@@ -18131,7 +18157,7 @@ var resolveBinding = (evidence, pin, currentCandidateId) => {
18131
18157
  candidateId: evidence.candidateId ?? fallback
18132
18158
  };
18133
18159
  };
18134
- var findingVerificationPasses = (findingCandidateId, evidence) => evidence.status === "passed" && (evidence.kind === "check" || evidence.kind === "review") && ((findingCandidateId ?? null) === null || evidence.candidateId === findingCandidateId);
18160
+ var findingVerificationPasses = (findingCandidateId, evidence) => evidence.status === "passed" && (evidence.kind === "check" || evidence.kind === "review") && ((findingCandidateId ?? null) === null || evidence.candidateId != null);
18135
18161
  var applicableDecision2 = (task, workspace, requirement, checkoutRoot) => task.decisions.filter((entry) => entry.provenance.kind !== "imported").map((entry) => entry.data).filter((decision) => decision.purpose === "limitation" && decision.response === "approved" && decision.revoked === null && decision.binding.taskId === task.id && decision.binding.workspaceId === workspace.id && decision.requirementIds.includes(requirement.id) && decision.binding.scope && scopeCovers2(decision.binding.scope, requirement.scope) && decision.digest === decisionDigest(decision) && (checkoutRoot ? verifyDecisionContentAtRoot(checkoutRoot, decision.binding).ok : decision.binding.contentRefs.every((reference) => reference.kind !== "file")));
18136
18162
  var applicableRequirementDecision = (task, workspace, requirement, checkoutRoot) => task.decisions.filter(({ data, provenance }) => provenance.kind !== "imported" && data.purpose !== "limitation" && (data.response === "approved" || data.response === "stated") && data.revoked === null && data.binding.taskId === task.id && data.binding.workspaceId === workspace.id && data.requirementIds.includes(requirement.id) && scopeCovers2(data.binding.scope, requirement.scope) && data.digest === decisionDigest(data) && (checkoutRoot ? verifyDecisionContentAtRoot(checkoutRoot, data.binding).ok : data.binding.contentRefs.every((reference) => reference.kind !== "file"))).map(({ id }) => ({ id }));
18137
18163
  var evidenceMatchesRequirement = (kind, evidenceKind, dimension, ruleId) => {
@@ -18366,6 +18392,11 @@ var exportDigest = (bundle) => sha256({
18366
18392
  task: bundle.task
18367
18393
  });
18368
18394
  // packages/workit-core/src/core/external-action.ts
18395
+ var chainStepSchema = union([
18396
+ string2().min(1),
18397
+ object({ branch: string2().min(1) }).strict(),
18398
+ object({ pr: literal(true) }).strict()
18399
+ ]);
18369
18400
  var externalActionSchema = discriminatedUnion("operation", [
18370
18401
  object({
18371
18402
  operation: literal("git.branch_setup"),
@@ -18380,7 +18411,7 @@ var externalActionSchema = discriminatedUnion("operation", [
18380
18411
  operation: literal("git.commit"),
18381
18412
  payload: object({
18382
18413
  message: string2().min(1).optional(),
18383
- plan_steps: array(string2().min(1)).optional(),
18414
+ plan_steps: array(chainStepSchema).min(1).max(32).optional(),
18384
18415
  plan_branch: string2().min(1).optional()
18385
18416
  }).strict()
18386
18417
  }).strict(),
@@ -18866,6 +18897,7 @@ var verifyNativeWorker = (verifier, input, binding) => {
18866
18897
  expectedWorkspaceRevision: expected.expectedWorkspaceRevision,
18867
18898
  state: expected.state,
18868
18899
  session: expected.session,
18900
+ report: expected.report ?? null,
18869
18901
  provenance: result.data,
18870
18902
  ...binding
18871
18903
  });
@@ -18876,7 +18908,7 @@ var takeWorker = (token, binding, expected) => {
18876
18908
  verifiedWorkers.delete(token);
18877
18909
  if (!value)
18878
18910
  return null;
18879
- if (value.owner !== binding.owner || value.store !== binding.store || value.root !== binding.root || value.root !== value.store.root || !sameValue(value.caller, binding.caller) || value.taskId !== expected.taskId || value.workerId !== expected.workerId || value.expectedRevision !== expected.expectedRevision || value.expectedWorkspaceRevision !== expected.expectedWorkspaceRevision || value.state !== expected.state || !sameValue(value.session, expected.session))
18911
+ if (value.owner !== binding.owner || value.store !== binding.store || value.root !== binding.root || value.root !== value.store.root || !sameValue(value.caller, binding.caller) || value.taskId !== expected.taskId || value.workerId !== expected.workerId || value.expectedRevision !== expected.expectedRevision || value.expectedWorkspaceRevision !== expected.expectedWorkspaceRevision || value.state !== expected.state || !sameValue(value.session, expected.session) || !sameValue(value.report, expected.report ?? null))
18880
18912
  return null;
18881
18913
  return value;
18882
18914
  };
@@ -18917,6 +18949,8 @@ var applyWorkerLifecycle = (input) => {
18917
18949
  return failure("invalid_transition", "worker already has an observed session");
18918
18950
  if (notStarted && !["dispatching", "cancelling"].includes(entry.data.state))
18919
18951
  return failure("invalid_transition", "worker launch was not claimed");
18952
+ if (input.report && input.state !== "stopped")
18953
+ return failure("invalid_input", "worker reports require a stopped worker");
18920
18954
  if ((input.state === "running" || input.state === "cancelling" || input.state === "stopped" && !notStarted) && !input.session)
18921
18955
  return failure("invalid_input", "running worker observations require a session");
18922
18956
  if (entry.data.session && !sameValue(entry.data.session, input.session))
@@ -18933,12 +18967,13 @@ var applyWorkerLifecycle = (input) => {
18933
18967
  data: {
18934
18968
  ...entry.data,
18935
18969
  state: terminalCancel ? "cancelling" : input.state,
18936
- session: input.session
18970
+ session: input.session,
18971
+ report: entry.data.report ?? input.report ?? null
18937
18972
  }
18938
18973
  };
18939
18974
  const shouldClear = input.state === "stopped" && workspace.data.writer !== null && workspace.data.writer.owner.taskId === task.data.id && workspace.data.writer.owner.workerId === input.workerId;
18940
18975
  const shouldUncertain = input.state === "unknown" && workspace.data.writer !== null && workspace.data.writer.owner.taskId === task.data.id && workspace.data.writer.owner.workerId === input.workerId;
18941
- if (entry.data.state === nextEntry.data.state && sameValue(entry.data.session, input.session) && !shouldClear && !shouldUncertain)
18976
+ if (entry.data.state === nextEntry.data.state && sameValue(entry.data.session, input.session) && sameValue(entry.data.report, nextEntry.data.report) && !shouldClear && !shouldUncertain)
18942
18977
  return success(task.data.revision, workspace.data.revision, entry);
18943
18978
  const changed = input.store.mutateTaskAndWorkspace({
18944
18979
  taskId: task.data.id,
@@ -19356,14 +19391,30 @@ class WorkitCore {
19356
19391
  const listed = this.store.listTasks();
19357
19392
  if (!listed.ok)
19358
19393
  return listed;
19359
- const summaries = [];
19360
- for (const task of listed.data) {
19361
- const summary = this.summary(task);
19362
- if (!summary.ok)
19363
- return summary;
19364
- summaries.push(summary.data);
19365
- }
19366
- return success(null, null, summaries);
19394
+ const status = input.status ?? "open";
19395
+ const limit = input.limit ?? 20;
19396
+ const selected = listed.data.filter((task) => status === "all" ? true : status === "closed" ? task.status === "closed" : task.status !== "closed").sort((left, right) => right.updatedAt.localeCompare(left.updatedAt)).slice(0, limit);
19397
+ if (selected.length === 0)
19398
+ return success(null, null, []);
19399
+ const workspace = this.store.readWorkspace();
19400
+ if (!workspace.ok)
19401
+ return workspace;
19402
+ if (!workspace.data)
19403
+ return failure("not_found", "workspace not found");
19404
+ const tasks = selected.map((task) => ({
19405
+ id: task.id,
19406
+ revision: task.revision,
19407
+ workspaceRevision: workspace.data.revision,
19408
+ createdAt: task.createdAt,
19409
+ updatedAt: task.updatedAt,
19410
+ runtime: task.runtime ?? null,
19411
+ objective: task.intent.data.objective,
19412
+ status: task.status,
19413
+ closure: task.closure,
19414
+ progress: task.progress,
19415
+ writer: task.status === "closed" ? null : workspace.data.writer
19416
+ }));
19417
+ return success(null, null, tasks);
19367
19418
  }
19368
19419
  case "inspect": {
19369
19420
  const task = this.store.readTask(input.taskId);
@@ -19372,7 +19423,7 @@ class WorkitCore {
19372
19423
  const helper = this.helperTaskGuard(task.data, true);
19373
19424
  if (!helper.ok)
19374
19425
  return helper;
19375
- if (input.view === "summary")
19426
+ if ((input.view ?? "summary") === "summary")
19376
19427
  return this.summary(task.data);
19377
19428
  return this.view(task.data);
19378
19429
  }
@@ -19716,7 +19767,7 @@ class WorkitCore {
19716
19767
  const evaluations = evaluateEvidence(task.data, current.data);
19717
19768
  const verified = evidence.some((entry) => {
19718
19769
  const evaluation = evaluations.find((item) => item.evidenceId === entry.id);
19719
- return findingVerificationPasses(finding.data.candidateId, {
19770
+ return entry.recordedAt >= finding.recordedAt && findingVerificationPasses(finding.data.candidateId, {
19720
19771
  kind: entry.data.kind,
19721
19772
  candidateId: entry.data.candidateId,
19722
19773
  status: evaluation?.status ?? "missing"
@@ -19796,7 +19847,18 @@ class WorkitCore {
19796
19847
  if (task.data.status !== "active")
19797
19848
  return failure("invalid_transition", "paused or closed tasks cannot assign workers");
19798
19849
  if (!bindingCovers(task.data.intent.data.scope, input.assignment.scope))
19799
- return failure("permission_denied", "worker assignment is outside task scope");
19850
+ return failure("permission_denied", "worker assignment is outside task scope", {
19851
+ fields: [
19852
+ {
19853
+ path: "assignment.scope",
19854
+ reason: `paths ${JSON.stringify(input.assignment.scope.paths)} must be contained by lead paths ${JSON.stringify(task.data.intent.data.scope.paths)}`
19855
+ },
19856
+ {
19857
+ path: "task.intent.scope",
19858
+ reason: `lead paths are ${JSON.stringify(task.data.intent.data.scope.paths)}`
19859
+ }
19860
+ ]
19861
+ });
19800
19862
  if (input.assignment.decisionIds.some((id) => !task.data.decisions.some((entry) => entry.id === id)))
19801
19863
  return failure("invalid_input", "worker assignment references an unknown decision");
19802
19864
  if (input.assignment.requirementIds.some((id) => !task.data.policy?.requirements.some((requirement) => requirement.id === id)))
@@ -20003,7 +20065,15 @@ class WorkitCore {
20003
20065
  ...item,
20004
20066
  recordedAt: mutation.now,
20005
20067
  provenance: attested.data,
20006
- data: { ...item.data, state: "dispatching" }
20068
+ data: {
20069
+ ...item.data,
20070
+ state: "dispatching",
20071
+ coordinator: {
20072
+ kind: "host",
20073
+ host: this.context.caller.host,
20074
+ handle: this.context.caller.actor
20075
+ }
20076
+ }
20007
20077
  } : item)
20008
20078
  });
20009
20079
  }
@@ -20079,6 +20149,7 @@ class WorkitCore {
20079
20149
  expectedWorkspaceRevision: input.expectedWorkspaceRevision,
20080
20150
  state: "stopped",
20081
20151
  session: null,
20152
+ report: null,
20082
20153
  provenance: attested.data,
20083
20154
  owner: this.authorityOwner,
20084
20155
  store: this.store,
@@ -20386,10 +20457,12 @@ class WorkitCore {
20386
20457
  return workspace;
20387
20458
  if (!workspace.data)
20388
20459
  return failure("not_found", "workspace not found");
20389
- const current = captureCandidate(this.store.root, task.intent.data.scope, environment());
20460
+ const historical = task.status === "closed" ? task.candidates.at(-1) : undefined;
20461
+ const current = historical ? success(null, null, historical) : captureCandidate(this.store.root, task.intent.data.scope, environment());
20390
20462
  if (!current.ok)
20391
20463
  return current;
20392
- const requirements = evaluateRequirements(task, workspace.data, this.context.capabilities, current.data, this.store.root, this.context.caller);
20464
+ const evaluationWorkspace = task.status === "closed" ? { ...workspace.data, writer: null } : workspace.data;
20465
+ const requirements = evaluateRequirements(task, evaluationWorkspace, this.context.capabilities, current.data, this.store.root, this.context.caller);
20393
20466
  return success(task.revision, workspace.data.revision, {
20394
20467
  id: task.id,
20395
20468
  revision: task.revision,
@@ -20403,7 +20476,7 @@ class WorkitCore {
20403
20476
  progress: task.progress,
20404
20477
  policy: task.policy,
20405
20478
  requirements,
20406
- writer: workspace.data.writer
20479
+ writer: evaluationWorkspace.writer
20407
20480
  });
20408
20481
  }
20409
20482
  view(task) {
@@ -20412,13 +20485,15 @@ class WorkitCore {
20412
20485
  return workspace;
20413
20486
  if (!workspace.data)
20414
20487
  return failure("not_found", "workspace not found");
20415
- const current = captureCandidate(this.store.root, task.intent.data.scope, environment());
20488
+ const historical = task.status === "closed" ? task.candidates.at(-1) : undefined;
20489
+ const current = historical ? success(null, null, historical) : captureCandidate(this.store.root, task.intent.data.scope, environment());
20416
20490
  if (!current.ok)
20417
20491
  return current;
20418
- const requirements = evaluateRequirements(task, workspace.data, this.context.capabilities, current.data, this.store.root, this.context.caller);
20492
+ const evaluationWorkspace = task.status === "closed" ? { ...workspace.data, writer: null } : workspace.data;
20493
+ const requirements = evaluateRequirements(task, evaluationWorkspace, this.context.capabilities, current.data, this.store.root, this.context.caller);
20419
20494
  return success(task.revision, workspace.data.revision, {
20420
20495
  task,
20421
- workspace: workspace.data,
20496
+ workspace: evaluationWorkspace,
20422
20497
  capabilities: this.context.capabilities,
20423
20498
  requirements,
20424
20499
  evidence: evaluateEvidence(task, current.data)
@@ -20509,8 +20584,6 @@ class WorkitCore {
20509
20584
  return helper;
20510
20585
  if (status === "paused" && task.data.status !== "active" || status === "active" && task.data.status !== "paused")
20511
20586
  return failure("invalid_transition", `cannot transition ${task.data.status} to ${status}`);
20512
- if (status === "active" && input.authorityRefs.length === 0)
20513
- return failure("permission_denied", "resuming a task requires authority references");
20514
20587
  const workspace = this.store.readWorkspace();
20515
20588
  if (!workspace.ok)
20516
20589
  return workspace;
@@ -20540,7 +20613,7 @@ class WorkitCore {
20540
20613
  return failure("needs_input", "imported task requires fresh destination evidence");
20541
20614
  if (current.data.blockers.some((blocker) => blocker.dependentAction === "resume" || blocker.reason === "worker state requires reconciliation"))
20542
20615
  return failure("recovery_required", "imported task requires resume reconciliation");
20543
- if (!validResumeApproval(task.data, workspace.data, input.authorityRefs, this.context))
20616
+ if (!validResumeApproval(task.data, workspace.data, input.authorityRefs ?? [], this.context))
20544
20617
  return failure("permission_denied", "imported resume requires native destination approval");
20545
20618
  resumeCandidate = current.data.candidate;
20546
20619
  }
@@ -20670,7 +20743,7 @@ class WorkitCore {
20670
20743
  task: (value, context) => success(context.revision, null, {
20671
20744
  ...value,
20672
20745
  status: "closed",
20673
- candidates: value.candidates.some((item) => item.id === withCandidate.id) ? value.candidates : [...value.candidates, withCandidate],
20746
+ candidates: taskForView.candidates,
20674
20747
  closure: {
20675
20748
  outcome: closure.data.outcome,
20676
20749
  at: context.now,
@@ -20745,7 +20818,7 @@ function run2(root, executable, args, env = {}) {
20745
20818
  var SUPPORT_MATRIX = {
20746
20819
  bun: "1.4.1",
20747
20820
  node: { minimum: "24", current: "24.20.0" },
20748
- opencode: { minimum: "1.15.0", current: "1.18.30" },
20821
+ opencode: { minimum: "1.18.30", current: "1.18.30" },
20749
20822
  codex: { cli: "0.153.4", desktopPackage: "26.901.20858", bundledCodexCli: "0.153.0-alpha.5" },
20750
20823
  os: ["ubuntu-latest", "macos-latest", "windows-latest"]
20751
20824
  };
@@ -7705,6 +7705,7 @@ var workerSchema = object({
7705
7705
  assignment: assignmentSchema,
7706
7706
  state: _enum(["assigned", "dispatching", "running", "cancelling", "stopped", "unknown"]),
7707
7707
  session: refSchema.nullable(),
7708
+ coordinator: refSchema.optional(),
7708
7709
  report: workerReportSchema.nullable()
7709
7710
  }).strict();
7710
7711
  var ownerSchema = object({
@@ -7816,6 +7817,7 @@ var taskSummarySchema = object({
7816
7817
  requirements: array(requirementEvaluationSchema),
7817
7818
  writer: workspaceRecordSchema.shape.writer
7818
7819
  }).strict();
7820
+ var taskListItemSchema = taskSummarySchema.omit({ policy: true, requirements: true });
7819
7821
  var exportBundleSchema = object({
7820
7822
  schemaVersion: literal(1),
7821
7823
  exportedAt: utc,
@@ -7837,11 +7839,15 @@ var taskOperations = {
7837
7839
  expectedWorkspaceRevision: revision.nullable().optional(),
7838
7840
  intent: intentSchema
7839
7841
  }),
7840
- list: operation({ action: literal("list") }),
7842
+ list: operation({
7843
+ action: literal("list"),
7844
+ status: _enum(["open", "closed", "all"]).optional(),
7845
+ limit: number2().int().min(1).max(50).optional()
7846
+ }),
7841
7847
  inspect: operation({
7842
7848
  action: literal("inspect"),
7843
7849
  ...taskId,
7844
- view: _enum(["summary", "full"])
7850
+ view: _enum(["summary", "full"]).optional()
7845
7851
  }),
7846
7852
  revise: operation({
7847
7853
  action: literal("revise"),
@@ -7869,7 +7875,7 @@ var taskOperations = {
7869
7875
  ...taskId,
7870
7876
  ...revisions,
7871
7877
  expectedWorkspaceRevision: revision.optional(),
7872
- authorityRefs: array(refSchema)
7878
+ authorityRefs: array(refSchema).optional()
7873
7879
  }),
7874
7880
  close: operation({
7875
7881
  action: literal("close"),
@@ -9641,6 +9647,10 @@ var validPath = (value) => typeof value === "string" && value.length > 0 && ![..
9641
9647
  }) && !value.split(/[\\/]/).includes("..");
9642
9648
  var callerValue = (value) => ({ host: value.host, actor: value.actor });
9643
9649
  var workerIdOf = (value) => value.workerId ?? null;
9650
+ var currentWriterOwnsTask = (task, workspace, caller) => {
9651
+ const owner = workspace.writer?.owner;
9652
+ return task.status === "active" && task.workspaceId === workspace.id && owner?.taskId === task.id && owner.session.host === caller.host && owner.session.handle === caller.actor;
9653
+ };
9644
9654
  function assertProductWriteAllowed(input) {
9645
9655
  if (!Array.isArray(input.paths) || input.paths.some((path) => !validPath(path)))
9646
9656
  return failure("invalid_input", "invalid product write path");
@@ -9998,9 +10008,11 @@ var standingReceiptFor = (root, workspace, cls, dir) => {
9998
10008
  var verifyStandingApproval = (root, task, caller, binding) => {
9999
10009
  if (task.status !== "active")
10000
10010
  return failure("invalid_transition", "only active tasks can authorize actions");
10001
- const session = task.intent?.provenance?.session;
10002
- if (!session || session.kind !== "host" || session.host !== caller.host || session.handle !== caller.actor)
10003
- return failure("permission_denied", "standing approval requires the lead session");
10011
+ const workspace = new TaskStore(root).readWorkspace();
10012
+ if (!workspace.ok)
10013
+ return workspace;
10014
+ if (!workspace.data || !currentWriterOwnsTask(task, workspace.data, caller))
10015
+ return failure("permission_denied", "standing approval requires the current writer session");
10004
10016
  const standing = binding.standing;
10005
10017
  if (!standing || typeof standing.workspace !== "string" || typeof standing.class !== "string")
10006
10018
  return failure("invalid_input", "standing approval needs a workspace and class");
@@ -10237,6 +10249,20 @@ var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
10237
10249
  };
10238
10250
  var verifyContentRefs = (store, binding) => verifyDecisionContentAtRoot(store.root, binding);
10239
10251
  var storedDecisionApplicable = (store, task, purpose, binding) => task.decisions.filter((entry) => entry.provenance.kind !== "imported" && decisionMatches(entry, purpose, binding) && verifyDecisionContentAtRoot(store.root, entry.data.binding).ok);
10252
+ var approvalAuthorityMatches = (store, task, approval, current) => {
10253
+ if (approval.kind !== "host_observed" || approval.receipts.length === 0)
10254
+ return false;
10255
+ if (provenanceMatches(approval, current))
10256
+ return true;
10257
+ const session = current.kind === "host_observed" ? current.session : null;
10258
+ if (!session || session.kind !== "host")
10259
+ return false;
10260
+ const workspace = store.readWorkspace();
10261
+ return workspace.ok && workspace.data !== null && currentWriterOwnsTask(task, workspace.data, {
10262
+ host: session.host,
10263
+ actor: session.handle
10264
+ });
10265
+ };
10240
10266
  var validateAction = (store, task, workspaceId, input, authority) => {
10241
10267
  if (task.status !== "active")
10242
10268
  return failure("invalid_transition", "only active tasks can authorize actions");
@@ -10262,7 +10288,7 @@ var validateAction = (store, task, workspaceId, input, authority) => {
10262
10288
  return failure("permission_denied", "native reservation authority does not match decision");
10263
10289
  if (decision.response !== "approved")
10264
10290
  return failure("permission_denied", "decision was rejected");
10265
- if (entry.provenance.kind !== "host_observed" || entry.provenance.receipts.length === 0 || !provenanceMatches(entry.provenance, authority.provenance))
10291
+ if (!approvalAuthorityMatches(store, task, entry.provenance, authority.provenance))
10266
10292
  return failure("permission_denied", "action approval lacks native receipt assurance");
10267
10293
  const receipts = entry.provenance.receipts;
10268
10294
  const standing = receipts.filter((receipt) => typeof receipt === "object" && receipt !== null && receipt.kind === "standing");
@@ -10429,7 +10455,7 @@ function settleAction(input) {
10429
10455
  return failure("not_found", "decision not found");
10430
10456
  if (!authorityDecisionMatches(authority, entry.data))
10431
10457
  return failure("permission_denied", "native settlement authority does not match decision");
10432
- if (!provenanceMatches(entry.provenance, authority.provenance))
10458
+ if (!approvalAuthorityMatches(input.store, current, entry.provenance, authority.provenance))
10433
10459
  return failure("permission_denied", "native settlement caller does not match approval");
10434
10460
  if (entry.data.purpose !== "action" || entry.data.digest !== decisionDigest(entry.data))
10435
10461
  return failure("permission_denied", "decision binding is invalid");
@@ -10528,7 +10554,7 @@ function reconcileAction(input) {
10528
10554
  const entry = current.decisions.find((candidate) => candidate.id === input.decisionId);
10529
10555
  if (!entry || entry.data.purpose !== "action")
10530
10556
  return failure("not_found", "decision not found");
10531
- if (!authorityDecisionMatches(authority, entry.data) || !provenanceMatches(entry.provenance, authority.provenance))
10557
+ if (!authorityDecisionMatches(authority, entry.data) || !approvalAuthorityMatches(input.store, current, entry.provenance, authority.provenance))
10532
10558
  return failure("permission_denied", "native reconciliation caller does not match approval");
10533
10559
  if (entry.data.response !== "approved" || entry.data.revoked !== null || entry.data.digest !== decisionDigest(entry.data) || entry.data.binding.taskId !== current.id || entry.data.binding.workspaceId !== current.workspaceId || entry.data.binding.workspaceId !== workspace.data.id)
10534
10560
  return failure("permission_denied", "reconciliation decision binding is invalid");
@@ -10865,7 +10891,7 @@ var resolveBinding = (evidence, pin, currentCandidateId) => {
10865
10891
  candidateId: evidence.candidateId ?? fallback
10866
10892
  };
10867
10893
  };
10868
- var findingVerificationPasses = (findingCandidateId, evidence) => evidence.status === "passed" && (evidence.kind === "check" || evidence.kind === "review") && ((findingCandidateId ?? null) === null || evidence.candidateId === findingCandidateId);
10894
+ var findingVerificationPasses = (findingCandidateId, evidence) => evidence.status === "passed" && (evidence.kind === "check" || evidence.kind === "review") && ((findingCandidateId ?? null) === null || evidence.candidateId != null);
10869
10895
  var applicableDecision2 = (task, workspace, requirement, checkoutRoot) => task.decisions.filter((entry) => entry.provenance.kind !== "imported").map((entry) => entry.data).filter((decision) => decision.purpose === "limitation" && decision.response === "approved" && decision.revoked === null && decision.binding.taskId === task.id && decision.binding.workspaceId === workspace.id && decision.requirementIds.includes(requirement.id) && decision.binding.scope && scopeCovers2(decision.binding.scope, requirement.scope) && decision.digest === decisionDigest(decision) && (checkoutRoot ? verifyDecisionContentAtRoot(checkoutRoot, decision.binding).ok : decision.binding.contentRefs.every((reference) => reference.kind !== "file")));
10870
10896
  var applicableRequirementDecision = (task, workspace, requirement, checkoutRoot) => task.decisions.filter(({ data, provenance }) => provenance.kind !== "imported" && data.purpose !== "limitation" && (data.response === "approved" || data.response === "stated") && data.revoked === null && data.binding.taskId === task.id && data.binding.workspaceId === workspace.id && data.requirementIds.includes(requirement.id) && scopeCovers2(data.binding.scope, requirement.scope) && data.digest === decisionDigest(data) && (checkoutRoot ? verifyDecisionContentAtRoot(checkoutRoot, data.binding).ok : data.binding.contentRefs.every((reference) => reference.kind !== "file"))).map(({ id }) => ({ id }));
10871
10897
  var evidenceMatchesRequirement = (kind, evidenceKind, dimension, ruleId) => {
@@ -11334,6 +11360,11 @@ function shouldDenyShellRoute(dir, command) {
11334
11360
  return shellRouteIntent(command);
11335
11361
  }
11336
11362
  // packages/workit-core/src/core/external-action.ts
11363
+ var chainStepSchema = union([
11364
+ string2().min(1),
11365
+ object({ branch: string2().min(1) }).strict(),
11366
+ object({ pr: literal(true) }).strict()
11367
+ ]);
11337
11368
  var externalActionSchema = discriminatedUnion("operation", [
11338
11369
  object({
11339
11370
  operation: literal("git.branch_setup"),
@@ -11348,7 +11379,7 @@ var externalActionSchema = discriminatedUnion("operation", [
11348
11379
  operation: literal("git.commit"),
11349
11380
  payload: object({
11350
11381
  message: string2().min(1).optional(),
11351
- plan_steps: array(string2().min(1)).optional(),
11382
+ plan_steps: array(chainStepSchema).min(1).max(32).optional(),
11352
11383
  plan_branch: string2().min(1).optional()
11353
11384
  }).strict()
11354
11385
  }).strict(),
@@ -11834,6 +11865,7 @@ var verifyNativeWorker = (verifier, input, binding) => {
11834
11865
  expectedWorkspaceRevision: expected.expectedWorkspaceRevision,
11835
11866
  state: expected.state,
11836
11867
  session: expected.session,
11868
+ report: expected.report ?? null,
11837
11869
  provenance: result.data,
11838
11870
  ...binding
11839
11871
  });
@@ -11844,7 +11876,7 @@ var takeWorker = (token, binding, expected) => {
11844
11876
  verifiedWorkers.delete(token);
11845
11877
  if (!value)
11846
11878
  return null;
11847
- if (value.owner !== binding.owner || value.store !== binding.store || value.root !== binding.root || value.root !== value.store.root || !sameValue(value.caller, binding.caller) || value.taskId !== expected.taskId || value.workerId !== expected.workerId || value.expectedRevision !== expected.expectedRevision || value.expectedWorkspaceRevision !== expected.expectedWorkspaceRevision || value.state !== expected.state || !sameValue(value.session, expected.session))
11879
+ if (value.owner !== binding.owner || value.store !== binding.store || value.root !== binding.root || value.root !== value.store.root || !sameValue(value.caller, binding.caller) || value.taskId !== expected.taskId || value.workerId !== expected.workerId || value.expectedRevision !== expected.expectedRevision || value.expectedWorkspaceRevision !== expected.expectedWorkspaceRevision || value.state !== expected.state || !sameValue(value.session, expected.session) || !sameValue(value.report, expected.report ?? null))
11848
11880
  return null;
11849
11881
  return value;
11850
11882
  };
@@ -11885,6 +11917,8 @@ var applyWorkerLifecycle = (input) => {
11885
11917
  return failure("invalid_transition", "worker already has an observed session");
11886
11918
  if (notStarted && !["dispatching", "cancelling"].includes(entry.data.state))
11887
11919
  return failure("invalid_transition", "worker launch was not claimed");
11920
+ if (input.report && input.state !== "stopped")
11921
+ return failure("invalid_input", "worker reports require a stopped worker");
11888
11922
  if ((input.state === "running" || input.state === "cancelling" || input.state === "stopped" && !notStarted) && !input.session)
11889
11923
  return failure("invalid_input", "running worker observations require a session");
11890
11924
  if (entry.data.session && !sameValue(entry.data.session, input.session))
@@ -11901,12 +11935,13 @@ var applyWorkerLifecycle = (input) => {
11901
11935
  data: {
11902
11936
  ...entry.data,
11903
11937
  state: terminalCancel ? "cancelling" : input.state,
11904
- session: input.session
11938
+ session: input.session,
11939
+ report: entry.data.report ?? input.report ?? null
11905
11940
  }
11906
11941
  };
11907
11942
  const shouldClear = input.state === "stopped" && workspace.data.writer !== null && workspace.data.writer.owner.taskId === task.data.id && workspace.data.writer.owner.workerId === input.workerId;
11908
11943
  const shouldUncertain = input.state === "unknown" && workspace.data.writer !== null && workspace.data.writer.owner.taskId === task.data.id && workspace.data.writer.owner.workerId === input.workerId;
11909
- if (entry.data.state === nextEntry.data.state && sameValue(entry.data.session, input.session) && !shouldClear && !shouldUncertain)
11944
+ if (entry.data.state === nextEntry.data.state && sameValue(entry.data.session, input.session) && sameValue(entry.data.report, nextEntry.data.report) && !shouldClear && !shouldUncertain)
11910
11945
  return success(task.data.revision, workspace.data.revision, entry);
11911
11946
  const changed = input.store.mutateTaskAndWorkspace({
11912
11947
  taskId: task.data.id,
@@ -12324,14 +12359,30 @@ class WorkitCore {
12324
12359
  const listed = this.store.listTasks();
12325
12360
  if (!listed.ok)
12326
12361
  return listed;
12327
- const summaries = [];
12328
- for (const task of listed.data) {
12329
- const summary = this.summary(task);
12330
- if (!summary.ok)
12331
- return summary;
12332
- summaries.push(summary.data);
12333
- }
12334
- return success(null, null, summaries);
12362
+ const status = input.status ?? "open";
12363
+ const limit = input.limit ?? 20;
12364
+ const selected = listed.data.filter((task) => status === "all" ? true : status === "closed" ? task.status === "closed" : task.status !== "closed").sort((left, right) => right.updatedAt.localeCompare(left.updatedAt)).slice(0, limit);
12365
+ if (selected.length === 0)
12366
+ return success(null, null, []);
12367
+ const workspace = this.store.readWorkspace();
12368
+ if (!workspace.ok)
12369
+ return workspace;
12370
+ if (!workspace.data)
12371
+ return failure("not_found", "workspace not found");
12372
+ const tasks = selected.map((task) => ({
12373
+ id: task.id,
12374
+ revision: task.revision,
12375
+ workspaceRevision: workspace.data.revision,
12376
+ createdAt: task.createdAt,
12377
+ updatedAt: task.updatedAt,
12378
+ runtime: task.runtime ?? null,
12379
+ objective: task.intent.data.objective,
12380
+ status: task.status,
12381
+ closure: task.closure,
12382
+ progress: task.progress,
12383
+ writer: task.status === "closed" ? null : workspace.data.writer
12384
+ }));
12385
+ return success(null, null, tasks);
12335
12386
  }
12336
12387
  case "inspect": {
12337
12388
  const task = this.store.readTask(input.taskId);
@@ -12340,7 +12391,7 @@ class WorkitCore {
12340
12391
  const helper = this.helperTaskGuard(task.data, true);
12341
12392
  if (!helper.ok)
12342
12393
  return helper;
12343
- if (input.view === "summary")
12394
+ if ((input.view ?? "summary") === "summary")
12344
12395
  return this.summary(task.data);
12345
12396
  return this.view(task.data);
12346
12397
  }
@@ -12684,7 +12735,7 @@ class WorkitCore {
12684
12735
  const evaluations = evaluateEvidence(task.data, current.data);
12685
12736
  const verified = evidence.some((entry) => {
12686
12737
  const evaluation = evaluations.find((item) => item.evidenceId === entry.id);
12687
- return findingVerificationPasses(finding.data.candidateId, {
12738
+ return entry.recordedAt >= finding.recordedAt && findingVerificationPasses(finding.data.candidateId, {
12688
12739
  kind: entry.data.kind,
12689
12740
  candidateId: entry.data.candidateId,
12690
12741
  status: evaluation?.status ?? "missing"
@@ -12764,7 +12815,18 @@ class WorkitCore {
12764
12815
  if (task.data.status !== "active")
12765
12816
  return failure("invalid_transition", "paused or closed tasks cannot assign workers");
12766
12817
  if (!bindingCovers(task.data.intent.data.scope, input.assignment.scope))
12767
- return failure("permission_denied", "worker assignment is outside task scope");
12818
+ return failure("permission_denied", "worker assignment is outside task scope", {
12819
+ fields: [
12820
+ {
12821
+ path: "assignment.scope",
12822
+ reason: `paths ${JSON.stringify(input.assignment.scope.paths)} must be contained by lead paths ${JSON.stringify(task.data.intent.data.scope.paths)}`
12823
+ },
12824
+ {
12825
+ path: "task.intent.scope",
12826
+ reason: `lead paths are ${JSON.stringify(task.data.intent.data.scope.paths)}`
12827
+ }
12828
+ ]
12829
+ });
12768
12830
  if (input.assignment.decisionIds.some((id) => !task.data.decisions.some((entry) => entry.id === id)))
12769
12831
  return failure("invalid_input", "worker assignment references an unknown decision");
12770
12832
  if (input.assignment.requirementIds.some((id) => !task.data.policy?.requirements.some((requirement) => requirement.id === id)))
@@ -12971,7 +13033,15 @@ class WorkitCore {
12971
13033
  ...item,
12972
13034
  recordedAt: mutation.now,
12973
13035
  provenance: attested.data,
12974
- data: { ...item.data, state: "dispatching" }
13036
+ data: {
13037
+ ...item.data,
13038
+ state: "dispatching",
13039
+ coordinator: {
13040
+ kind: "host",
13041
+ host: this.context.caller.host,
13042
+ handle: this.context.caller.actor
13043
+ }
13044
+ }
12975
13045
  } : item)
12976
13046
  });
12977
13047
  }
@@ -13047,6 +13117,7 @@ class WorkitCore {
13047
13117
  expectedWorkspaceRevision: input.expectedWorkspaceRevision,
13048
13118
  state: "stopped",
13049
13119
  session: null,
13120
+ report: null,
13050
13121
  provenance: attested.data,
13051
13122
  owner: this.authorityOwner,
13052
13123
  store: this.store,
@@ -13354,10 +13425,12 @@ class WorkitCore {
13354
13425
  return workspace;
13355
13426
  if (!workspace.data)
13356
13427
  return failure("not_found", "workspace not found");
13357
- const current = captureCandidate(this.store.root, task.intent.data.scope, environment());
13428
+ const historical = task.status === "closed" ? task.candidates.at(-1) : undefined;
13429
+ const current = historical ? success(null, null, historical) : captureCandidate(this.store.root, task.intent.data.scope, environment());
13358
13430
  if (!current.ok)
13359
13431
  return current;
13360
- const requirements = evaluateRequirements(task, workspace.data, this.context.capabilities, current.data, this.store.root, this.context.caller);
13432
+ const evaluationWorkspace = task.status === "closed" ? { ...workspace.data, writer: null } : workspace.data;
13433
+ const requirements = evaluateRequirements(task, evaluationWorkspace, this.context.capabilities, current.data, this.store.root, this.context.caller);
13361
13434
  return success(task.revision, workspace.data.revision, {
13362
13435
  id: task.id,
13363
13436
  revision: task.revision,
@@ -13371,7 +13444,7 @@ class WorkitCore {
13371
13444
  progress: task.progress,
13372
13445
  policy: task.policy,
13373
13446
  requirements,
13374
- writer: workspace.data.writer
13447
+ writer: evaluationWorkspace.writer
13375
13448
  });
13376
13449
  }
13377
13450
  view(task) {
@@ -13380,13 +13453,15 @@ class WorkitCore {
13380
13453
  return workspace;
13381
13454
  if (!workspace.data)
13382
13455
  return failure("not_found", "workspace not found");
13383
- const current = captureCandidate(this.store.root, task.intent.data.scope, environment());
13456
+ const historical = task.status === "closed" ? task.candidates.at(-1) : undefined;
13457
+ const current = historical ? success(null, null, historical) : captureCandidate(this.store.root, task.intent.data.scope, environment());
13384
13458
  if (!current.ok)
13385
13459
  return current;
13386
- const requirements = evaluateRequirements(task, workspace.data, this.context.capabilities, current.data, this.store.root, this.context.caller);
13460
+ const evaluationWorkspace = task.status === "closed" ? { ...workspace.data, writer: null } : workspace.data;
13461
+ const requirements = evaluateRequirements(task, evaluationWorkspace, this.context.capabilities, current.data, this.store.root, this.context.caller);
13387
13462
  return success(task.revision, workspace.data.revision, {
13388
13463
  task,
13389
- workspace: workspace.data,
13464
+ workspace: evaluationWorkspace,
13390
13465
  capabilities: this.context.capabilities,
13391
13466
  requirements,
13392
13467
  evidence: evaluateEvidence(task, current.data)
@@ -13477,8 +13552,6 @@ class WorkitCore {
13477
13552
  return helper;
13478
13553
  if (status === "paused" && task.data.status !== "active" || status === "active" && task.data.status !== "paused")
13479
13554
  return failure("invalid_transition", `cannot transition ${task.data.status} to ${status}`);
13480
- if (status === "active" && input.authorityRefs.length === 0)
13481
- return failure("permission_denied", "resuming a task requires authority references");
13482
13555
  const workspace = this.store.readWorkspace();
13483
13556
  if (!workspace.ok)
13484
13557
  return workspace;
@@ -13508,7 +13581,7 @@ class WorkitCore {
13508
13581
  return failure("needs_input", "imported task requires fresh destination evidence");
13509
13582
  if (current.data.blockers.some((blocker) => blocker.dependentAction === "resume" || blocker.reason === "worker state requires reconciliation"))
13510
13583
  return failure("recovery_required", "imported task requires resume reconciliation");
13511
- if (!validResumeApproval(task.data, workspace.data, input.authorityRefs, this.context))
13584
+ if (!validResumeApproval(task.data, workspace.data, input.authorityRefs ?? [], this.context))
13512
13585
  return failure("permission_denied", "imported resume requires native destination approval");
13513
13586
  resumeCandidate = current.data.candidate;
13514
13587
  }
@@ -13638,7 +13711,7 @@ class WorkitCore {
13638
13711
  task: (value, context) => success(context.revision, null, {
13639
13712
  ...value,
13640
13713
  status: "closed",
13641
- candidates: value.candidates.some((item) => item.id === withCandidate.id) ? value.candidates : [...value.candidates, withCandidate],
13714
+ candidates: taskForView.candidates,
13642
13715
  closure: {
13643
13716
  outcome: closure.data.outcome,
13644
13717
  at: context.now,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brainervirus/workit-codex",
3
- "version": "1.1.1",
3
+ "version": "1.2.1",
4
4
  "private": false,
5
5
  "description": "Workit Codex CLI/desktop plugin — shared MCP transport, hooks, and fourteen method skills",
6
6
  "keywords": [
@@ -38,8 +38,8 @@
38
38
  "build": "bun scripts/build.ts"
39
39
  },
40
40
  "dependencies": {
41
- "@brainervirus/workit-core": "^1.1.1",
42
- "@brainervirus/workit-mcp": "^1.1.1"
41
+ "@brainervirus/workit-core": "^1.2.1",
42
+ "@brainervirus/workit-mcp": "^1.2.1"
43
43
  },
44
44
  "engines": {
45
45
  "node": ">=24"