@brainervirus/workit-codex 1.0.8 → 1.0.9

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.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "Adaptive engineering workflow rails for Codex",
5
5
  "author": {
6
6
  "name": "BrainerVirus"
@@ -14457,7 +14457,7 @@ var workerReportSchema = object({
14457
14457
  }).strict();
14458
14458
  var workerSchema = object({
14459
14459
  assignment: assignmentSchema,
14460
- state: _enum(["assigned", "running", "cancelling", "stopped", "unknown"]),
14460
+ state: _enum(["assigned", "dispatching", "running", "cancelling", "stopped", "unknown"]),
14461
14461
  session: refSchema.nullable(),
14462
14462
  report: workerReportSchema.nullable()
14463
14463
  }).strict();
@@ -17291,7 +17291,7 @@ function reconcileResume(view, observations = []) {
17291
17291
  return candidate;
17292
17292
  const staleEvidenceIds = evaluateEvidence(view.task, candidate.data).filter((entry) => entry.status === "stale").map((entry) => entry.evidenceId);
17293
17293
  const blockers = [...view.task.progress.blockers];
17294
- if (view.task.workers.some((entry) => ["running", "cancelling", "unknown"].includes(entry.data.state)))
17294
+ if (view.task.workers.some((entry) => ["dispatching", "running", "cancelling", "unknown"].includes(entry.data.state)))
17295
17295
  blockers.push({
17296
17296
  reason: "worker state requires reconciliation",
17297
17297
  dependentAction: "resume",
@@ -17899,10 +17899,10 @@ var applyWorkerLifecycle = (input) => {
17899
17899
  const notStarted = input.dispatch === true;
17900
17900
  if (notStarted && (input.state !== "stopped" || input.session !== null))
17901
17901
  return failure("invalid_input", "a never-dispatched worker stops with no session");
17902
- if (notStarted && (entry.data.state === "stopped" || entry.data.state === "unknown"))
17903
- return failure("invalid_transition", "worker is no longer awaiting dispatch");
17904
- if (notStarted && (entry.data.session !== null || entry.data.state === "running"))
17902
+ if (notStarted && entry.data.session !== null)
17905
17903
  return failure("invalid_transition", "worker already has an observed session");
17904
+ if (notStarted && !["dispatching", "cancelling"].includes(entry.data.state))
17905
+ return failure("invalid_transition", "worker launch was not claimed");
17906
17906
  if ((input.state === "running" || input.state === "cancelling" || input.state === "stopped" && !notStarted) && !input.session)
17907
17907
  return failure("invalid_input", "running worker observations require a session");
17908
17908
  if (entry.data.session && !sameValue(entry.data.session, input.session))
@@ -18289,7 +18289,7 @@ class WorkitCore {
18289
18289
  activeWorkerBlocker(task, workspace) {
18290
18290
  if (workspace.writer)
18291
18291
  return failure("recovery_required", "writer ownership must be released first");
18292
- if (task.workers.some((entry) => ["running", "cancelling", "unknown"].includes(entry.data.state)))
18292
+ if (task.workers.some((entry) => ["dispatching", "running", "cancelling", "unknown"].includes(entry.data.state)))
18293
18293
  return failure("recovery_required", "worker state requires reconciliation");
18294
18294
  return null;
18295
18295
  }
@@ -19053,7 +19053,12 @@ class WorkitCore {
19053
19053
  return failure("invalid_transition", "worker is not awaiting dispatch");
19054
19054
  return success(mutation.revision, null, {
19055
19055
  ...current,
19056
- workers: current.workers.map((item) => item.id === input.workerId ? { ...item, recordedAt: mutation.now, provenance: attested.data } : item)
19056
+ workers: current.workers.map((item) => item.id === input.workerId ? {
19057
+ ...item,
19058
+ recordedAt: mutation.now,
19059
+ provenance: attested.data,
19060
+ data: { ...item.data, state: "dispatching" }
19061
+ } : item)
19057
19062
  });
19058
19063
  }
19059
19064
  });
@@ -19522,7 +19527,7 @@ class WorkitCore {
19522
19527
  const base = reconcileResume(effectiveView);
19523
19528
  if (!base.ok)
19524
19529
  return base;
19525
- const needsReconciliation = view.task.workers.some((entry) => ["running", "cancelling", "unknown"].includes(observedStates.get(entry.id) ?? entry.data.state));
19530
+ const needsReconciliation = view.task.workers.some((entry) => ["dispatching", "running", "cancelling", "unknown"].includes(observedStates.get(entry.id) ?? entry.data.state));
19526
19531
  const blockers = [...base.data.blockers];
19527
19532
  if (needsReconciliation && !blockers.some((entry) => entry.reason === "worker state requires reconciliation"))
19528
19533
  blockers.push({
@@ -7611,7 +7611,7 @@ var workerReportSchema = object({
7611
7611
  }).strict();
7612
7612
  var workerSchema = object({
7613
7613
  assignment: assignmentSchema,
7614
- state: _enum(["assigned", "running", "cancelling", "stopped", "unknown"]),
7614
+ state: _enum(["assigned", "dispatching", "running", "cancelling", "stopped", "unknown"]),
7615
7615
  session: refSchema.nullable(),
7616
7616
  report: workerReportSchema.nullable()
7617
7617
  }).strict();
@@ -10380,6 +10380,95 @@ function evaluateClosure(requestedOutcome, view) {
10380
10380
  });
10381
10381
  }
10382
10382
 
10383
+ // packages/workit-core/src/core/methods.ts
10384
+ var METHODS = {
10385
+ "workit-challenge": { dimensions: ["challenge", "decisions"] },
10386
+ "workit-behavioral-tdd": { dimensions: ["testing"] },
10387
+ "workit-review": { dimensions: ["review"] },
10388
+ "workit-plan": { dimensions: ["artifacts", "continuity"] },
10389
+ "workit-implement": { dimensions: ["delegation"] },
10390
+ "workit-debug": { ruleIds: ["root-cause-investigation"] },
10391
+ "workit-handoff": { ruleIds: ["durable-handoff"] },
10392
+ "workit-deslop": { ruleIds: ["pre-pr-cleanup"] }
10393
+ };
10394
+ var methodMatches = (id, definition, requirement) => definition.dimensions?.includes(requirement.dimension) === true && !(id === "workit-review" && requirement.ruleId === "self-review") || definition.ruleIds?.includes(requirement.ruleId) === true;
10395
+ var assuranceFor = (id, definition, capabilities) => {
10396
+ const keys = new Set([
10397
+ id,
10398
+ ...definition.dimensions ?? [],
10399
+ ...definition.ruleIds ?? []
10400
+ ]);
10401
+ const matches = capabilities.filter((capability) => keys.has(capability.name) || keys.has(capability.surface));
10402
+ if (id === "workit-review" && matches.length === 0)
10403
+ return { assurance: "unavailable", reasons: ["independent review capability is unavailable"] };
10404
+ if (matches.some((capability) => capability.assurance === "unavailable"))
10405
+ return {
10406
+ assurance: "unavailable",
10407
+ reasons: matches.filter((capability) => capability.assurance === "unavailable").map((capability) => capability.reason)
10408
+ };
10409
+ if (matches.some((capability) => capability.assurance === "enforced"))
10410
+ return { assurance: "enforced", reasons: matches.map((capability) => capability.reason) };
10411
+ return { assurance: "agent_guided", reasons: matches.map((capability) => capability.reason) };
10412
+ };
10413
+ function selectMethods(policy, capabilities) {
10414
+ return Object.entries(METHODS).flatMap(([id, definition]) => {
10415
+ const requirements = policy.requirements.filter((requirement) => methodMatches(id, definition, requirement));
10416
+ if (requirements.length === 0)
10417
+ return [];
10418
+ const capability = assuranceFor(id, definition, capabilities);
10419
+ const reasons = [
10420
+ ...new Set(requirements.map((requirement) => requirement.reason)),
10421
+ ...capability.reasons
10422
+ ];
10423
+ if (capability.assurance === "unavailable")
10424
+ reasons.unshift("required capability is unavailable");
10425
+ return [{ id, reason: reasons.join("; "), assurance: capability.assurance }];
10426
+ });
10427
+ }
10428
+ var invariantBootstrap = () => `
10429
+ Workit keeps one accountable lead and one shared task state. Inspect current task
10430
+ state before acting. An empty task.list means no session yet, not permission to
10431
+ skip Workit; for user-requested product, debug, or behavior work with no active
10432
+ or paused task, run task.start then policy.assess before other product mutations.
10433
+ Omitted expectedRevision, expectedWorkspaceRevision, and writer workerId default
10434
+ to the current records; explicit values are still concurrency-checked, so never
10435
+ copy revisions between calls. Happy path: task.list, task.start {intent} with no
10436
+ revisions, policy.assess {assessment: {facts, signals, consequences,
10437
+ verification}} where facts are inferred or observed with file refs,
10438
+ writer.acquire {taskId} before product writes, evidence.record {evidence} where
10439
+ check and review kinds auto-bind the current tree and need no digests. Record
10440
+ self-review requirements with kind review and reviewContext matching your own
10441
+ host session; the lead may also record checks. Fresh-context review requires a
10442
+ session distinct from the task creator and every other evidence recorder. Record
10443
+ verification evidence last: later evidence or commits can reopen fixed findings
10444
+ for re-verification, so verify, resolve, then close with nothing in between.
10445
+ decision.record {binding with taskId/workspaceId from inspect plus presented and
10446
+ approvedContent} only through a native approval question asked receipt-shaped:
10447
+ header Workit decision: <purpose>, the same label repeated in the question
10448
+ text (some host UIs do not render headers), exactly two options approved and
10449
+ rejected; ask once, never re-ask to mint a receipt. task.close {outcome,
10450
+ summary, decisionIds}. A completed native subagent run stops its bound worker
10451
+ by itself; if a worker strands in cancelling with its run verifiably over,
10452
+ repeat worker.cancel {reason} to confirm the stop. Check and review evidence
10453
+ without a bound candidate goes stale; findings close only as fixed with passing
10454
+ verification, dismissed with supporting evidence, or deferred under an approved
10455
+ limitation. Use only the
10456
+ shared operations for task, policy, evidence, finding, decision, worker, writer,
10457
+ and state changes. Authority is bounded by the requested scope, current
10458
+ revision, caller/session provenance, and observed capabilities. Never claim host
10459
+ enforcement or evidence that the host cannot provide. Shell-executed writes are
10460
+ unattested agent-guided work even when a writer is held. Preserve unresolved
10461
+ requirements, gaps, and uncertain workers. Skill routing: slash aliases /wk-*
10462
+ always load on demand. Model-invoked: new instructions, interruptions, or
10463
+ forgotten items mid-task → load workit-steer before responding; about to open
10464
+ a PR or fresh from implementing → load workit-deslop; CI red → load
10465
+ workit-green-run; small-looking change before close or merge → load
10466
+ workit-blast-radius; ambiguous, consequential, or disputed proposal before
10467
+ recommending → load workit-challenge; spec or plan needs a flow diagram →
10468
+ load workit-diagram, a UI sketch → load workit-mockup. Load the skill; never
10469
+ act from memory of it.
10470
+ `.trim();
10471
+
10383
10472
  // packages/workit-core/src/core/task-context.ts
10384
10473
  function reconcileResume(view, observations = []) {
10385
10474
  if (observations.length > 0)
@@ -10389,7 +10478,7 @@ function reconcileResume(view, observations = []) {
10389
10478
  return candidate;
10390
10479
  const staleEvidenceIds = evaluateEvidence(view.task, candidate.data).filter((entry) => entry.status === "stale").map((entry) => entry.evidenceId);
10391
10480
  const blockers = [...view.task.progress.blockers];
10392
- if (view.task.workers.some((entry) => ["running", "cancelling", "unknown"].includes(entry.data.state)))
10481
+ if (view.task.workers.some((entry) => ["dispatching", "running", "cancelling", "unknown"].includes(entry.data.state)))
10393
10482
  blockers.push({
10394
10483
  reason: "worker state requires reconciliation",
10395
10484
  dependentAction: "resume",
@@ -10439,6 +10528,11 @@ function compactTaskContext(view) {
10439
10528
  digest: entry.data.digest,
10440
10529
  references: entry.data.binding.contentRefs.slice(0, 1).map(compactReference)
10441
10530
  }));
10531
+ const methods = view.task.policy ? selectMethods(view.task.policy, view.capabilities).map((method) => ({
10532
+ id: method.id,
10533
+ assurance: method.assurance,
10534
+ reason: compactText(method.reason, COMPACT_TEXT_BYTES) ?? ""
10535
+ })) : [];
10442
10536
  const gaps = Array.from(new Set([
10443
10537
  ...view.evidence.filter((entry) => entry.status === "stale").map((entry) => `stale evidence: ${entry.evidenceId}`),
10444
10538
  ...view.requirements.filter((entry) => entry.status !== "satisfied").map((entry) => entry.reason),
@@ -10448,15 +10542,18 @@ function compactTaskContext(view) {
10448
10542
  objective: compactText(view.task.intent.data.objective, COMPACT_TEXT_BYTES) ?? "",
10449
10543
  status: view.task.status,
10450
10544
  decisions,
10545
+ methods,
10451
10546
  gaps,
10452
10547
  nextAction: compactText(view.task.progress.nextAction, COMPACT_TEXT_BYTES)
10453
10548
  };
10454
10549
  let encoded = JSON.stringify(context);
10455
- while (compactBytes(encoded) > COMPACT_MAX_BYTES && (context.decisions.length || context.gaps.length)) {
10550
+ while (compactBytes(encoded) > COMPACT_MAX_BYTES && (context.decisions.length || context.methods.length || context.gaps.length)) {
10456
10551
  if (context.gaps.length)
10457
10552
  context.gaps.pop();
10458
- else
10553
+ else if (context.decisions.length)
10459
10554
  context.decisions.pop();
10555
+ else
10556
+ context.methods.pop();
10460
10557
  encoded = JSON.stringify(context);
10461
10558
  }
10462
10559
  if (compactBytes(encoded) > COMPACT_MAX_BYTES) {
@@ -10472,50 +10569,47 @@ var exportDigest = (bundle) => sha256({
10472
10569
  sourceWorkspaceId: bundle.sourceWorkspaceId,
10473
10570
  task: bundle.task
10474
10571
  });
10475
- // packages/workit-core/src/core/methods.ts
10476
- var invariantBootstrap = () => `
10477
- Workit keeps one accountable lead and one shared task state. Inspect current task
10478
- state before acting. An empty task.list means no session yet, not permission to
10479
- skip Workit; for user-requested product, debug, or behavior work with no active
10480
- or paused task, run task.start then policy.assess before other product mutations.
10481
- Omitted expectedRevision, expectedWorkspaceRevision, and writer workerId default
10482
- to the current records; explicit values are still concurrency-checked, so never
10483
- copy revisions between calls. Happy path: task.list, task.start {intent} with no
10484
- revisions, policy.assess {assessment: {facts, signals, consequences,
10485
- verification}} where facts are inferred or observed with file refs,
10486
- writer.acquire {taskId} before product writes, evidence.record {evidence} where
10487
- check and review kinds auto-bind the current tree and need no digests. Record
10488
- self-review requirements with kind review and reviewContext matching your own
10489
- host session; the lead may also record checks. Fresh-context review requires a
10490
- session distinct from the task creator and every other evidence recorder. Record
10491
- verification evidence last: later evidence or commits can reopen fixed findings
10492
- for re-verification, so verify, resolve, then close with nothing in between.
10493
- decision.record {binding with taskId/workspaceId from inspect plus presented and
10494
- approvedContent} only through a native approval question asked receipt-shaped:
10495
- header Workit decision: <purpose>, the same label repeated in the question
10496
- text (some host UIs do not render headers), exactly two options approved and
10497
- rejected; ask once, never re-ask to mint a receipt. task.close {outcome,
10498
- summary, decisionIds}. A completed native subagent run stops its bound worker
10499
- by itself; if a worker strands in cancelling with its run verifiably over,
10500
- repeat worker.cancel {reason} to confirm the stop. Check and review evidence
10501
- without a bound candidate goes stale; findings close only as fixed with passing
10502
- verification, dismissed with supporting evidence, or deferred under an approved
10503
- limitation. Use only the
10504
- shared operations for task, policy, evidence, finding, decision, worker, writer,
10505
- and state changes. Authority is bounded by the requested scope, current
10506
- revision, caller/session provenance, and observed capabilities. Never claim host
10507
- enforcement or evidence that the host cannot provide. Shell-executed writes are
10508
- unattested agent-guided work even when a writer is held. Preserve unresolved
10509
- requirements, gaps, and uncertain workers. Skill routing: slash aliases /wk-*
10510
- always load on demand. Model-invoked: new instructions, interruptions, or
10511
- forgotten items mid-task → load workit-steer before responding; about to open
10512
- a PR or fresh from implementing → load workit-deslop; CI red → load
10513
- workit-green-run; small-looking change before close or merge → load
10514
- workit-blast-radius; ambiguous, consequential, or disputed proposal before
10515
- recommending → load workit-challenge; spec or plan needs a flow diagram →
10516
- load workit-diagram, a UI sketch → load workit-mockup. Load the skill; never
10517
- act from memory of it.
10518
- `.trim();
10572
+ // packages/workit-core/src/core/route-intent.ts
10573
+ var GUIDANCE = {
10574
+ "git.branch_setup": "use the Workit git.branch_setup action (workit_external_action in hosts, or `workit action git.branch_setup --payload '{}' --confirm --json` in the CLI)",
10575
+ "hosting.pull_request": "use the Workit hosting.pull_request action (workit_external_action in hosts, or `workit action hosting.pull_request --payload '{...}' --confirm --json` in the CLI), then drive the created PR through workit-babysit"
10576
+ };
10577
+ var unbalancedQuotes = (segment) => {
10578
+ const text = segment.replace(/\\./gu, "");
10579
+ return (text.match(/"/gu)?.length ?? 0) % 2 !== 0 || (text.match(/'/gu)?.length ?? 0) % 2 !== 0;
10580
+ };
10581
+ var segmentTokens = (segment) => {
10582
+ if (segment.includes("`") || segment.includes("$("))
10583
+ return null;
10584
+ if (unbalancedQuotes(segment))
10585
+ return null;
10586
+ const parts = segment.trim().split(/\s+/u);
10587
+ while (parts.length > 0 && /^[A-Za-z_][A-Za-z0-9_]*=/u.test(parts[0]))
10588
+ parts.shift();
10589
+ return parts.length > 0 ? parts : null;
10590
+ };
10591
+ var unquote = (token) => token.replace(/^['"]|['"]$/gu, "");
10592
+ function shellRouteIntent(command) {
10593
+ if (typeof command !== "string" || command.trim() === "")
10594
+ return null;
10595
+ for (const raw of command.split(/&&|\|\||;|\n/u)) {
10596
+ const parts = segmentTokens(raw);
10597
+ if (!parts)
10598
+ continue;
10599
+ const head = unquote(parts[0]);
10600
+ const second = unquote(parts[1] ?? "");
10601
+ const third = unquote(parts[2] ?? "");
10602
+ if (head === "git" && second === "switch" && (third === "-c" || third === "--create"))
10603
+ return { route: "git.branch_setup", guidance: GUIDANCE["git.branch_setup"] };
10604
+ if (head === "git" && second === "checkout" && (third === "-b" || third === "-B"))
10605
+ return { route: "git.branch_setup", guidance: GUIDANCE["git.branch_setup"] };
10606
+ if (head === "gh" && second === "pr" && third === "create")
10607
+ return { route: "hosting.pull_request", guidance: GUIDANCE["hosting.pull_request"] };
10608
+ if (head === "glab" && second === "mr" && third === "create")
10609
+ return { route: "hosting.pull_request", guidance: GUIDANCE["hosting.pull_request"] };
10610
+ }
10611
+ return null;
10612
+ }
10519
10613
  // packages/workit-core/src/core/external-action.ts
10520
10614
  var externalActionSchema = discriminatedUnion("operation", [
10521
10615
  object({
@@ -11104,10 +11198,10 @@ var applyWorkerLifecycle = (input) => {
11104
11198
  const notStarted = input.dispatch === true;
11105
11199
  if (notStarted && (input.state !== "stopped" || input.session !== null))
11106
11200
  return failure("invalid_input", "a never-dispatched worker stops with no session");
11107
- if (notStarted && (entry.data.state === "stopped" || entry.data.state === "unknown"))
11108
- return failure("invalid_transition", "worker is no longer awaiting dispatch");
11109
- if (notStarted && (entry.data.session !== null || entry.data.state === "running"))
11201
+ if (notStarted && entry.data.session !== null)
11110
11202
  return failure("invalid_transition", "worker already has an observed session");
11203
+ if (notStarted && !["dispatching", "cancelling"].includes(entry.data.state))
11204
+ return failure("invalid_transition", "worker launch was not claimed");
11111
11205
  if ((input.state === "running" || input.state === "cancelling" || input.state === "stopped" && !notStarted) && !input.session)
11112
11206
  return failure("invalid_input", "running worker observations require a session");
11113
11207
  if (entry.data.session && !sameValue(entry.data.session, input.session))
@@ -11494,7 +11588,7 @@ class WorkitCore {
11494
11588
  activeWorkerBlocker(task, workspace) {
11495
11589
  if (workspace.writer)
11496
11590
  return failure("recovery_required", "writer ownership must be released first");
11497
- if (task.workers.some((entry) => ["running", "cancelling", "unknown"].includes(entry.data.state)))
11591
+ if (task.workers.some((entry) => ["dispatching", "running", "cancelling", "unknown"].includes(entry.data.state)))
11498
11592
  return failure("recovery_required", "worker state requires reconciliation");
11499
11593
  return null;
11500
11594
  }
@@ -12258,7 +12352,12 @@ class WorkitCore {
12258
12352
  return failure("invalid_transition", "worker is not awaiting dispatch");
12259
12353
  return success(mutation.revision, null, {
12260
12354
  ...current,
12261
- workers: current.workers.map((item) => item.id === input.workerId ? { ...item, recordedAt: mutation.now, provenance: attested.data } : item)
12355
+ workers: current.workers.map((item) => item.id === input.workerId ? {
12356
+ ...item,
12357
+ recordedAt: mutation.now,
12358
+ provenance: attested.data,
12359
+ data: { ...item.data, state: "dispatching" }
12360
+ } : item)
12262
12361
  });
12263
12362
  }
12264
12363
  });
@@ -12727,7 +12826,7 @@ class WorkitCore {
12727
12826
  const base = reconcileResume(effectiveView);
12728
12827
  if (!base.ok)
12729
12828
  return base;
12730
- const needsReconciliation = view.task.workers.some((entry) => ["running", "cancelling", "unknown"].includes(observedStates.get(entry.id) ?? entry.data.state));
12829
+ const needsReconciliation = view.task.workers.some((entry) => ["dispatching", "running", "cancelling", "unknown"].includes(observedStates.get(entry.id) ?? entry.data.state));
12731
12830
  const blockers = [...base.data.blockers];
12732
12831
  if (needsReconciliation && !blockers.some((entry) => entry.reason === "worker state requires reconciliation"))
12733
12832
  blockers.push({
@@ -13151,6 +13250,12 @@ var handleCodexHook = (raw) => {
13151
13250
  return output("SessionStart", { additionalContext: sessionContext(input) });
13152
13251
  }
13153
13252
  if (input.hook_event_name === "PreToolUse") {
13253
+ if (["bash", "unified-exec"].includes(String(input.tool_name).toLowerCase())) {
13254
+ const command = record2(input.tool_input) ? input.tool_input.command : undefined;
13255
+ const route = typeof command === "string" ? shellRouteIntent(command) : null;
13256
+ if (route)
13257
+ return denied("PreToolUse", `direct branch or PR creation bypasses the Workit route; ${route.guidance}`);
13258
+ }
13154
13259
  return output("PreToolUse", { permissionDecision: "allow" });
13155
13260
  }
13156
13261
  if (input.hook_event_name === "SubagentStart")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brainervirus/workit-codex",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
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.0.8",
42
- "@brainervirus/workit-mcp": "^1.0.8"
41
+ "@brainervirus/workit-core": "^1.0.9",
42
+ "@brainervirus/workit-mcp": "^1.0.9"
43
43
  },
44
44
  "engines": {
45
45
  "node": ">=24"
@@ -7,7 +7,9 @@ description: Use after creating a PR (auto-starts, drive default), when a PR nee
7
7
 
8
8
  Babysit starts automatically on PR creation unless declined (`babysit:false`).
9
9
  One babysitter per PR; never mutate PR topology (no rebase strategy changes,
10
- no force-push).
10
+ no force-push). When a PR URL is observed from a route Workit did not enforce
11
+ (for example a raw `gh pr create` the host allowed), load this skill and drive
12
+ that PR anyway; do not claim the Workit route was enforced.
11
13
 
12
14
  ## Before method work
13
15