@brainervirus/workit-cursor 0.8.8 → 0.8.10

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.
@@ -20868,7 +20868,7 @@ var resolveBranchPolicyFor = (workspaceRoot) => resolveBranchPolicy(readConfig()
20868
20868
  if (dirty) {
20869
20869
  if (stash !== "yes") {
20870
20870
  return {
20871
- error: "dirty working tree — ask with native question, then call workflow_branch_setup with stash=yes"
20871
+ error: "dirty working tree — ask with native question, then call workit_branch_setup with stash=yes"
20872
20872
  };
20873
20873
  }
20874
20874
  try {
@@ -21621,7 +21621,7 @@ var runGit = (cwd, args) => {
21621
21621
  - Entries should be human-readable and user-facing.
21622
21622
  - Do not use raw commit messages as changelog bullets.
21623
21623
  - MERGE into existing ### Category under [Unreleased] — never append a second ### Added / ### Fixed block.
21624
- - Apply with the native workflow_changelog_apply tool only (not hand-edits under Unreleased).
21624
+ - Apply with the native workit_changelog_apply tool only (not hand-edits under Unreleased).
21625
21625
  - If Unreleased already has duplicate category headings, normalize_only first.`;
21626
21626
  var init_repo_context = __esm(() => {
21627
21627
  init_vcs_config();
@@ -24182,7 +24182,7 @@ function sddContext({
24182
24182
  task_count,
24183
24183
  flow: { spec: flow.spec, plan: flow.plan, menu: flow.menu },
24184
24184
  todowrite_required: true,
24185
- todowrite_hint: "REQUIRED: Call OpenCode todowrite with todos from this result so the native task list shows progress. Before each task set status in_progress; after workflow_sdd_append_progress set it completed."
24185
+ todowrite_hint: "REQUIRED: Call OpenCode todowrite with todos from this result so the native task list shows progress. Before each task set status in_progress; after workit_sdd_append_progress set it completed."
24186
24186
  };
24187
24187
  }
24188
24188
  function sddTaskBrief({
@@ -24266,6 +24266,58 @@ function sddAppendProgress({
24266
24266
  const rel = posix2(path19.relative(contained.base, path_));
24267
24267
  return { ok: true, line: trimmed, progress_path: rel };
24268
24268
  }
24269
+ function sddAppendAdvisory({
24270
+ advisories_path,
24271
+ task_id,
24272
+ text,
24273
+ workspace_root
24274
+ }) {
24275
+ if (typeof task_id !== "number" || !Number.isSafeInteger(task_id) || task_id <= 0) {
24276
+ return { error: "task_id must be a positive safe integer", code: "advisory_task_invalid" };
24277
+ }
24278
+ if (typeof text !== "string") {
24279
+ return {
24280
+ error: "advisory text must be a string of 1-1000 characters after normalization",
24281
+ code: "advisory_text_invalid"
24282
+ };
24283
+ }
24284
+ if (text.includes("\r") || text.includes(`
24285
+ `)) {
24286
+ return {
24287
+ error: "advisory text must be a single line (no CR/LF)",
24288
+ code: "advisory_text_invalid"
24289
+ };
24290
+ }
24291
+ const collapsed = text.trim().replace(/[ \t]+/g, " ");
24292
+ if (collapsed.length === 0 || collapsed.length > 1000) {
24293
+ return {
24294
+ error: "advisory text must be 1-1000 characters after trim and horizontal-space collapse",
24295
+ code: "advisory_text_invalid"
24296
+ };
24297
+ }
24298
+ if (!/^docs\/[^/]+\/sdd\/advisories\.md$/.test(advisories_path)) {
24299
+ return {
24300
+ error: `advisories_path must be docs/<slug>/sdd/advisories.md: ${advisories_path}`,
24301
+ code: "advisory_path_invalid"
24302
+ };
24303
+ }
24304
+ const contained = resolveDocsPath({ workspace_root, path: advisories_path });
24305
+ if (!contained.ok)
24306
+ return { error: contained.error, code: "advisory_path_invalid" };
24307
+ const abs = contained.path;
24308
+ if (existsSync11(abs) && statSync6(abs).isDirectory()) {
24309
+ return {
24310
+ error: `advisory target is a directory: ${advisories_path}`,
24311
+ code: "advisory_target_invalid"
24312
+ };
24313
+ }
24314
+ mkdirSync6(path19.dirname(abs), { recursive: true });
24315
+ const line = `- Task ${task_id}: ${collapsed}
24316
+ `;
24317
+ appendFileSync2(abs, line, "utf8");
24318
+ const rel = posix2(path19.relative(contained.base, abs));
24319
+ return { ok: true, advisory: collapsed, advisories_path: rel };
24320
+ }
24269
24321
  var posix2 = (p) => p.split(path19.sep).join("/"), PROGRESS_RE;
24270
24322
  var init_sdd = __esm(() => {
24271
24323
  init_docs_validate();
@@ -24286,6 +24338,7 @@ import {
24286
24338
  fsyncSync,
24287
24339
  mkdirSync as mkdirSync7,
24288
24340
  openSync,
24341
+ readdirSync as readdirSync6,
24289
24342
  readFileSync as readFileSync13,
24290
24343
  renameSync,
24291
24344
  rmSync,
@@ -24298,16 +24351,20 @@ import path20 from "node:path";
24298
24351
 
24299
24352
  class HostReceiptStore {
24300
24353
  #bySession = new Map;
24301
- record(sessionId, callID, selectedLabel, recordedAt = Date.now(), question) {
24302
- const label = selectedLabel.trim();
24303
- if (!label)
24354
+ record(sessionId, callID, selectedLabel, recordedAt = Date.now(), question = "", purpose) {
24355
+ const trimmed = selectedLabel.trim();
24356
+ if (!trimmed)
24304
24357
  return;
24305
24358
  if (recordedAt > Date.now() + MAX_CLOCK_SKEW_MS)
24306
24359
  return;
24360
+ const derived = purpose ?? receiptPurposeForLabel(selectedLabel);
24361
+ if (derived === undefined)
24362
+ return;
24363
+ const q = question ?? "";
24307
24364
  const queue = this.#bySession.get(sessionId) ?? [];
24308
24365
  if (queue.length >= MAX_RECEIPTS_PER_SESSION)
24309
24366
  queue.shift();
24310
- queue.push({ sessionId, callID, selectedLabel: label, recordedAt, question });
24367
+ queue.push({ sessionId, callID, selectedLabel, recordedAt, question: q, purpose: derived });
24311
24368
  this.#bySession.set(sessionId, queue);
24312
24369
  }
24313
24370
  count(sessionId) {
@@ -24324,10 +24381,40 @@ class HostReceiptStore {
24324
24381
  if (!queue || queue.length === 0) {
24325
24382
  return err2("receipt_missing", "no host-observed native-question receipt for this session — ask the native " + "`question` tool and have the user answer before calling this tool");
24326
24383
  }
24327
- const index = queue.length - 1;
24384
+ let index = -1;
24385
+ if (opts.purpose !== undefined) {
24386
+ const top = queue[queue.length - 1];
24387
+ if (top && top.purpose === opts.purpose && isNegativeLabel(top.selectedLabel)) {
24388
+ const filtered = queue.filter((r) => r.purpose !== opts.purpose);
24389
+ if (filtered.length === 0)
24390
+ this.#bySession.delete(sessionId);
24391
+ else
24392
+ this.#bySession.set(sessionId, filtered);
24393
+ return err2("receipt_rejected", `the user's most recent answer (${JSON.stringify(top.selectedLabel)}) is a ` + "negative answer — it cannot authorize an approval; ask the native question again");
24394
+ }
24395
+ for (let i = queue.length - 1;i >= 0; i--) {
24396
+ if (queue[i].purpose === opts.purpose) {
24397
+ index = i;
24398
+ break;
24399
+ }
24400
+ }
24401
+ if (index === -1) {
24402
+ return err2("receipt_missing", `no host-observed receipt for purpose ${JSON.stringify(opts.purpose)} — ask the native question for that purpose`);
24403
+ }
24404
+ } else {
24405
+ index = queue.length - 1;
24406
+ }
24328
24407
  const receipt = queue[index];
24329
24408
  if (isNegativeLabel(receipt.selectedLabel)) {
24330
- this.#bySession.delete(sessionId);
24409
+ if (opts.purpose !== undefined) {
24410
+ const filtered = queue.filter((r) => r.purpose !== opts.purpose);
24411
+ if (filtered.length === 0)
24412
+ this.#bySession.delete(sessionId);
24413
+ else
24414
+ this.#bySession.set(sessionId, filtered);
24415
+ } else {
24416
+ this.#bySession.delete(sessionId);
24417
+ }
24331
24418
  return err2("receipt_rejected", `the user's most recent answer (${JSON.stringify(receipt.selectedLabel)}) is a ` + "negative answer — it cannot authorize an approval; ask the native question again");
24332
24419
  }
24333
24420
  if (opts.label !== undefined && !sameChoiceLabel(receipt.selectedLabel, opts.label)) {
@@ -24396,7 +24483,8 @@ var COORDINATOR_RECOVERY_TEXT, CURSOR_SUBAGENT_UNSUPPORTED_TEXT, MENU_CHOICES, e
24396
24483
  execution: {
24397
24484
  status: execution.status ?? "pending",
24398
24485
  mode: execution.mode ?? null,
24399
- evidence: execution.evidence ?? null
24486
+ evidence: execution.evidence ?? null,
24487
+ coordinator_session_id: execution.coordinator_session_id ?? null
24400
24488
  },
24401
24489
  handoff_destination: p.handoff_destination ?? false,
24402
24490
  updated_at: p.updated_at ?? Date.now()
@@ -24407,7 +24495,7 @@ var COORDINATOR_RECOVERY_TEXT, CURSOR_SUBAGENT_UNSUPPORTED_TEXT, MENU_CHOICES, e
24407
24495
  spec: { path: "", status: "draft", evidence: null, approved_digest: null },
24408
24496
  plan: { path: "", status: "draft", evidence: null, approved_digest: null },
24409
24497
  menu: { presented: false, chosen: "", evidence: null },
24410
- execution: { status: "pending", mode: null, evidence: null },
24498
+ execution: { status: "pending", mode: null, evidence: null, coordinator_session_id: null },
24411
24499
  handoff_destination: false,
24412
24500
  updated_at: Date.now()
24413
24501
  }), readFlowState = (root, slug) => {
@@ -24516,6 +24604,12 @@ var COORDINATOR_RECOVERY_TEXT, CURSOR_SUBAGENT_UNSUPPORTED_TEXT, MENU_CHOICES, e
24516
24604
  if (execRaw?.evidence !== undefined && !validateEvidenceValue(execRaw.evidence, true)) {
24517
24605
  return { ok: false, error: "flow state execution.evidence has an unsupported shape" };
24518
24606
  }
24607
+ if (execRaw?.coordinator_session_id !== undefined && execRaw.coordinator_session_id !== null && typeof execRaw.coordinator_session_id !== "string") {
24608
+ return {
24609
+ ok: false,
24610
+ error: "flow state execution.coordinator_session_id must be a string or null"
24611
+ };
24612
+ }
24519
24613
  return {
24520
24614
  ok: true,
24521
24615
  state: {
@@ -24531,7 +24625,8 @@ var COORDINATOR_RECOVERY_TEXT, CURSOR_SUBAGENT_UNSUPPORTED_TEXT, MENU_CHOICES, e
24531
24625
  execution: {
24532
24626
  status: execRaw?.status ?? "pending",
24533
24627
  mode: execRaw?.mode ?? null,
24534
- evidence: execRaw?.evidence ?? null
24628
+ evidence: execRaw?.evidence ?? null,
24629
+ coordinator_session_id: execRaw?.coordinator_session_id ?? null
24535
24630
  },
24536
24631
  handoff_destination: parsed.handoff_destination ?? false,
24537
24632
  updated_at: parsed.updated_at ?? Date.now()
@@ -24541,7 +24636,7 @@ var COORDINATOR_RECOVERY_TEXT, CURSOR_SUBAGENT_UNSUPPORTED_TEXT, MENU_CHOICES, e
24541
24636
  const file = flowPath(root, slug);
24542
24637
  const rel = path20.posix.join("docs", slug, "sdd", "flow.json");
24543
24638
  if (!existsSync12(file)) {
24544
- return err2("flow_not_activated", `flow not activated for ${slug} — run workflow_flow_status first`);
24639
+ return err2("flow_not_activated", `flow not activated for ${slug} — run workit_flow_status first`);
24545
24640
  }
24546
24641
  let text;
24547
24642
  try {
@@ -24658,7 +24753,7 @@ var COORDINATOR_RECOVERY_TEXT, CURSOR_SUBAGENT_UNSUPPORTED_TEXT, MENU_CHOICES, e
24658
24753
  spec: { ...state.spec, status: "draft", evidence: null, approved_digest: null },
24659
24754
  plan: { ...state.plan, status: "draft", evidence: null, approved_digest: null },
24660
24755
  menu: { presented: false, chosen: "", evidence: null },
24661
- execution: { status: "pending", mode: null, evidence: null },
24756
+ execution: { status: "pending", mode: null, evidence: null, coordinator_session_id: null },
24662
24757
  handoff_destination: false,
24663
24758
  updated_at: Date.now()
24664
24759
  }), resetForPlanDrift = (state) => ({
@@ -24697,9 +24792,14 @@ var COORDINATOR_RECOVERY_TEXT, CURSOR_SUBAGENT_UNSUPPORTED_TEXT, MENU_CHOICES, e
24697
24792
  }, deriveLegacyExecution = (root, slug, state) => {
24698
24793
  const ledger = ledgerCompletion(root, slug);
24699
24794
  if (state.plan.status === "approved" && state.menu.chosen === "subagent-driven" && ledger.started && !ledger.complete) {
24700
- return { status: "active", mode: "subagent-driven", evidence: null };
24795
+ return {
24796
+ status: "active",
24797
+ mode: "subagent-driven",
24798
+ evidence: null,
24799
+ coordinator_session_id: null
24800
+ };
24701
24801
  }
24702
- return { status: "pending", mode: null, evidence: null };
24802
+ return { status: "pending", mode: null, evidence: null, coordinator_session_id: null };
24703
24803
  }, normalizeCompatibility = (root, slug, parsed, state) => {
24704
24804
  if (!isRecord(parsed) || !("execution" in parsed)) {
24705
24805
  const derived = deriveLegacyExecution(root, slug, state);
@@ -24707,6 +24807,11 @@ var COORDINATOR_RECOVERY_TEXT, CURSOR_SUBAGENT_UNSUPPORTED_TEXT, MENU_CHOICES, e
24707
24807
  if (derived.status !== current.status || derived.mode !== current.mode) {
24708
24808
  return { state: { ...state, execution: derived, updated_at: Date.now() }, changed: true };
24709
24809
  }
24810
+ return { state, changed: false };
24811
+ }
24812
+ const execRaw = isRecord(parsed.execution) ? parsed.execution : undefined;
24813
+ if (execRaw && !("coordinator_session_id" in execRaw)) {
24814
+ return { state: { ...state, updated_at: Date.now() }, changed: true };
24710
24815
  }
24711
24816
  return { state, changed: false };
24712
24817
  }, withFlowLock = (file, fn) => {
@@ -24836,14 +24941,6 @@ var COORDINATOR_RECOVERY_TEXT, CURSOR_SUBAGENT_UNSUPPORTED_TEXT, MENU_CHOICES, e
24836
24941
  return err2("workspace_mismatch", `mutation context workspace ${JSON.stringify(ctx.hostWorkspace)} does not match flow workspace ${JSON.stringify(root)}`);
24837
24942
  }
24838
24943
  return { ok: true };
24839
- }, assertCoordinatorBoundary = (ctx, state) => {
24840
- if (ctx?.role === "coordinator" && state.execution.status === "active" && state.execution.mode === "subagent-driven") {
24841
- return err2("coordinator_blocked", COORDINATOR_RECOVERY_TEXT);
24842
- }
24843
- if (ctx?.role === "delegated" && !ctx.taskIdentity) {
24844
- return err2("delegated_unauthenticated", "delegated mutations require an authenticated task identity (taskIdentity) — re-run inside the delegated worker session");
24845
- }
24846
- return { ok: true };
24847
24944
  }, MAX_CLOCK_SKEW_MS = 60000, MAX_RECEIPTS_PER_SESSION = 10, RECEIPT_FRESHNESS_MS, EVIDENCE_WINDOW_MS, NEGATIVE_ANSWER_LABELS, isNegativeLabel = (label) => {
24848
24945
  const normalized = label.trim().toLowerCase();
24849
24946
  return NEGATIVE_ANSWER_LABELS.some((entry) => {
@@ -24854,6 +24951,31 @@ var COORDINATOR_RECOVERY_TEXT, CURSOR_SUBAGENT_UNSUPPORTED_TEXT, MENU_CHOICES, e
24854
24951
  }
24855
24952
  return firstWord.replace(/[^a-z]/g, "") === entry;
24856
24953
  });
24954
+ }, receiptPurposeForLabel = (label) => {
24955
+ const n = normalizeLabel(label);
24956
+ if (n === "approve spec" || n === "approve spec recommended")
24957
+ return "spec-approval";
24958
+ if (n === "approve plan" || n === "approve plan recommended")
24959
+ return "plan-approval";
24960
+ if (n === "approve")
24961
+ return;
24962
+ if (n === "pause plan")
24963
+ return "plan-pause";
24964
+ if (n === "resume plan")
24965
+ return "plan-resume";
24966
+ if (n === "complete plan")
24967
+ return "plan-complete";
24968
+ const exec = new Set([
24969
+ "subagent driven",
24970
+ "inline",
24971
+ "handoff",
24972
+ "review spec",
24973
+ "review plan",
24974
+ "change model"
24975
+ ]);
24976
+ if (exec.has(n))
24977
+ return "execution-menu";
24978
+ return;
24857
24979
  }, sameChoiceLabel = (a, b) => normalizeLabel(a) === normalizeLabel(b), normalizeLabel = (s) => s.replace(/\s*\([^)]*\)/g, " ").replace(/\s*\bfirst\b\s*$/i, " ").replace(/[^a-z0-9]+/gi, " ").trim().toLowerCase(), createCursorConfirmation = () => ({
24858
24980
  ok: true,
24859
24981
  evidence: { host: "cursor", attested: false, confirmation: "contract" }
@@ -24958,7 +25080,7 @@ var COORDINATOR_RECOVERY_TEXT, CURSOR_SUBAGENT_UNSUPPORTED_TEXT, MENU_CHOICES, e
24958
25080
  spec: { path: specPath, status: "draft", evidence: null, approved_digest: null },
24959
25081
  plan: { path: planPath, status: "draft", evidence: null, approved_digest: null },
24960
25082
  menu: { presented: false, chosen: "", evidence: null },
24961
- execution: { status: "pending", mode: null, evidence: null },
25083
+ execution: { status: "pending", mode: null, evidence: null, coordinator_session_id: null },
24962
25084
  handoff_destination: false,
24963
25085
  updated_at: Date.now()
24964
25086
  });
@@ -25101,13 +25223,24 @@ var COORDINATOR_RECOVERY_TEXT, CURSOR_SUBAGENT_UNSUPPORTED_TEXT, MENU_CHOICES, e
25101
25223
  return err2("recursive_handoff", "this flow is already a handoff destination — a second handoff is rejected");
25102
25224
  }
25103
25225
  const executing = choice === "subagent-driven" || choice === "inline";
25226
+ const coordinatorSessionId = choice === "subagent-driven" && recorded.evidence.host === "opencode" ? ctx?.sessionId ?? null : null;
25104
25227
  return {
25105
25228
  ok: true,
25106
25229
  next: {
25107
25230
  ...state,
25108
25231
  plan: { ...state.plan, path: state.plan.path || `docs/${slug}/plan.md` },
25109
25232
  menu: { presented: true, chosen: choice, evidence: recorded.evidence },
25110
- execution: executing ? { status: "active", mode: choice, evidence: recorded.evidence } : { status: "pending", mode: null, evidence: recorded.evidence },
25233
+ execution: executing ? {
25234
+ status: "active",
25235
+ mode: choice,
25236
+ evidence: recorded.evidence,
25237
+ coordinator_session_id: coordinatorSessionId
25238
+ } : {
25239
+ status: "pending",
25240
+ mode: null,
25241
+ evidence: recorded.evidence,
25242
+ coordinator_session_id: null
25243
+ },
25111
25244
  updated_at: Date.now()
25112
25245
  }
25113
25246
  };
@@ -25195,7 +25328,7 @@ var COORDINATOR_RECOVERY_TEXT, CURSOR_SUBAGENT_UNSUPPORTED_TEXT, MENU_CHOICES, e
25195
25328
  }
25196
25329
  const next = {
25197
25330
  ...reconciled.state,
25198
- execution: { ...exec, status: "completed" },
25331
+ execution: { ...exec, status: "completed", coordinator_session_id: null },
25199
25332
  handoff_destination: false,
25200
25333
  updated_at: Date.now()
25201
25334
  };
@@ -25255,7 +25388,7 @@ var COORDINATOR_RECOVERY_TEXT, CURSOR_SUBAGENT_UNSUPPORTED_TEXT, MENU_CHOICES, e
25255
25388
  }, slugFromSddPath = (p) => {
25256
25389
  const match = p.split(path20.sep).join("/").match(/^docs\/([^/]+)\/sdd(\/|$|['"])/);
25257
25390
  return match?.[1] ?? "";
25258
- }, assertProductGates = (root, slug, opts = {}, ctx) => {
25391
+ }, assertSddControlGates = (root, slug, opts = {}, ctx) => {
25259
25392
  const bound = assertMutationWorkspace(root, ctx);
25260
25393
  if (!bound.ok)
25261
25394
  return bound;
@@ -25264,13 +25397,13 @@ var COORDINATOR_RECOVERY_TEXT, CURSOR_SUBAGENT_UNSUPPORTED_TEXT, MENU_CHOICES, e
25264
25397
  return effective;
25265
25398
  const state = effective.state;
25266
25399
  if (state.spec.status !== "approved") {
25267
- return err2("spec_not_approved", `spec not approved (status: ${state.spec.status}). Run workflow_spec_approve after the user's approval.`);
25400
+ return err2("spec_not_approved", `spec not approved (status: ${state.spec.status}). Run workit_spec_approve after the user's approval.`);
25268
25401
  }
25269
25402
  if (state.plan.status !== "approved") {
25270
- return err2("plan_not_approved", `plan not approved (status: ${state.plan.status}). Run workflow_plan_approve after the user's approval.`);
25403
+ return err2("plan_not_approved", `plan not approved (status: ${state.plan.status}). Run workit_plan_approve after the user's approval.`);
25271
25404
  }
25272
25405
  if (opts.requireMenu && !state.menu.presented) {
25273
- return err2("menu_not_presented", "post-plan menu not presented. Record the native question answer with workflow_plan_menu.");
25406
+ return err2("menu_not_presented", "post-plan menu not presented. Record the native question answer with workit_plan_menu.");
25274
25407
  }
25275
25408
  if (opts.requireDocs) {
25276
25409
  const validated = docsValidate({
@@ -25281,15 +25414,18 @@ var COORDINATOR_RECOVERY_TEXT, CURSOR_SUBAGENT_UNSUPPORTED_TEXT, MENU_CHOICES, e
25281
25414
  if (validated.ok === false)
25282
25415
  return err2("docs_invalid", validated.error);
25283
25416
  }
25284
- return assertCoordinatorBoundary(ctx, state);
25285
- }, BASH_READ_TOKENS, BASH_GIT_READ_SUBCOMMANDS, BASH_GIT_MUTABLE_SUBCOMMANDS, BASH_GIT_READ_FLAGS, BASH_FIND_DENIED_FLAGS, BASH_TEST_VERBS, BASH_DENIED_HEADS, BASH_OUTPUT_FLAG_VERBS, BASH_PAREN_EXEMPT_HEADS, BASH_GIT_VALUE_FLAGS, COORDINATOR_SHELL_DENIED_TEXT;
25417
+ if (state.execution.status === "active" && state.execution.mode === "subagent-driven" && roleFromParentage(ctx?.parentSessionId, state.execution.coordinator_session_id) === "delegated") {
25418
+ return err2("sdd_control_denied", "SDD control metadata is coordinator-owned while a subagent-driven plan is active — delegated workers cannot mutate task briefs, review packages, progress, or advisories");
25419
+ }
25420
+ return { ok: true };
25421
+ }, roleFromParentage = (parentID, coordinatorSessionId) => typeof parentID === "string" && parentID !== "" && parentID === coordinatorSessionId ? "delegated" : "coordinator", BASH_READ_TOKENS, BASH_GIT_READ_SUBCOMMANDS, BASH_GIT_MUTABLE_SUBCOMMANDS, BASH_GIT_READ_FLAGS, BASH_FIND_DENIED_FLAGS, BASH_TEST_VERBS, BASH_DENIED_HEADS, BASH_OUTPUT_FLAG_VERBS, BASH_PAREN_EXEMPT_HEADS, BASH_GIT_VALUE_FLAGS, COORDINATOR_SHELL_DENIED_TEXT;
25286
25422
  var init_flow_state = __esm(() => {
25287
25423
  init_docs_validate();
25288
25424
  init_docs_layout();
25289
25425
  init_sdd();
25290
25426
  init_verify_project();
25291
25427
  init_menu();
25292
- COORDINATOR_RECOVERY_TEXT = "A subagent-driven plan is active: coordinator product edits are blocked. " + "Delegate product mutations (task briefs, progress, review packages) to an " + "authenticated delegated worker via `task` / `wk-implement` instead of " + "editing in the coordinator session.";
25428
+ COORDINATOR_RECOVERY_TEXT = "A subagent-driven plan is active: coordinator product edits are blocked. " + "Delegate product mutations to an authenticated delegated worker via `task` / `wk-implement` instead of " + "editing in the coordinator session.";
25293
25429
  CURSOR_SUBAGENT_UNSUPPORTED_TEXT = "Cursor cannot execute subagent-driven plans: the MCP has no child-session " + "support. Choose Inline, Handoff, or a review option in this session, or " + "run the plan in OpenCode with `wk-implement`.";
25294
25430
  MENU_CHOICES = [
25295
25431
  "subagent-driven",
@@ -25460,7 +25596,7 @@ import {
25460
25596
  existsSync as existsSync13,
25461
25597
  lstatSync as lstatSync2,
25462
25598
  mkdirSync as mkdirSync8,
25463
- readdirSync as readdirSync6,
25599
+ readdirSync as readdirSync7,
25464
25600
  readFileSync as readFileSync14,
25465
25601
  realpathSync as realpathSync3,
25466
25602
  renameSync as renameSync2,
@@ -25505,7 +25641,7 @@ var LEGACY_DIR = "docs/superpowers", MIGRATION_CHOICES, SLUG_RE3, RESERVED_SLUG
25505
25641
  const root = legacyRoot(workspace_root);
25506
25642
  const raw = [];
25507
25643
  if (existsSync13(root)) {
25508
- for (const entry of readdirSync6(root, { withFileTypes: true })) {
25644
+ for (const entry of readdirSync7(root, { withFileTypes: true })) {
25509
25645
  const abs = path21.join(root, entry.name);
25510
25646
  const rel = posix3(path21.relative(workspace_root, abs));
25511
25647
  if (entry.isDirectory()) {
@@ -25639,7 +25775,7 @@ var LEGACY_DIR = "docs/superpowers", MIGRATION_CHOICES, SLUG_RE3, RESERVED_SLUG
25639
25775
  if (visits.has(real))
25640
25776
  return { ok: true };
25641
25777
  visits.add(real);
25642
- for (const entry of readdirSync6(real, { withFileTypes: true })) {
25778
+ for (const entry of readdirSync7(real, { withFileTypes: true })) {
25643
25779
  const fromAbs = path21.join(real, entry.name);
25644
25780
  const fromRel = posix3(path21.join(legacyRel, entry.name));
25645
25781
  const toRel = posix3(path21.join(destRelRoot, entry.name));
@@ -25828,7 +25964,7 @@ var init_docs_migration = __esm(() => {
25828
25964
  });
25829
25965
 
25830
25966
  // packages/workit-core/src/core/docs-repo.ts
25831
- import { existsSync as existsSync14, mkdirSync as mkdirSync9, readFileSync as readFileSync15, writeFileSync as writeFileSync8, readdirSync as readdirSync7 } from "node:fs";
25967
+ import { existsSync as existsSync14, mkdirSync as mkdirSync9, readFileSync as readFileSync15, writeFileSync as writeFileSync8, readdirSync as readdirSync8 } from "node:fs";
25832
25968
  import { execFileSync as execFileSync6 } from "node:child_process";
25833
25969
  import path22 from "node:path";
25834
25970
  var configPath = () => process.env.WORKFLOW_DOCS_REPO_CONFIG ?? path22.join(configDir(), "docs-repo.json"), readDocsRepoConfig = () => {
@@ -25868,7 +26004,7 @@ var configPath = () => process.env.WORKFLOW_DOCS_REPO_CONFIG ?? path22.join(conf
25868
26004
  const specs = [];
25869
26005
  const docsDir = path22.join(workspaceRoot, "docs");
25870
26006
  if (existsSync14(docsDir)) {
25871
- for (const slug of readdirSync7(docsDir)) {
26007
+ for (const slug of readdirSync8(docsDir)) {
25872
26008
  if (slug.startsWith("."))
25873
26009
  continue;
25874
26010
  const spec = path22.posix.join("docs", slug, "spec.md");
@@ -25879,7 +26015,7 @@ var configPath = () => process.env.WORKFLOW_DOCS_REPO_CONFIG ?? path22.join(conf
25879
26015
  if (repoPath) {
25880
26016
  const featuresDir = path22.join(repoPath, "features");
25881
26017
  if (existsSync14(featuresDir)) {
25882
- const match = readdirSync7(featuresDir).find((d) => new RegExp(`^20\\d{2}-\\d{2}-${slug}$`).test(d));
26018
+ const match = readdirSync8(featuresDir).find((d) => new RegExp(`^20\\d{2}-\\d{2}-${slug}$`).test(d));
25883
26019
  if (match) {
25884
26020
  promoted = true;
25885
26021
  target = path22.join(repoPath, "features", match);
@@ -25918,7 +26054,7 @@ var configPath = () => process.env.WORKFLOW_DOCS_REPO_CONFIG ?? path22.join(conf
25918
26054
  const workspaceRootCanonical = resolved.layout.workspace;
25919
26055
  const repoPath = docsRepoPath();
25920
26056
  if (!repoPath)
25921
- return { ok: false, error: "docs repo not linked — run workflow_docs_repo_link" };
26057
+ return { ok: false, error: "docs repo not linked — run workit_docs_repo_link" };
25922
26058
  const repoValid = validateDocsRepo(repoPath);
25923
26059
  if (!repoValid.ok)
25924
26060
  return { ok: false, error: repoValid.error };
@@ -25966,7 +26102,7 @@ var configPath = () => process.env.WORKFLOW_DOCS_REPO_CONFIG ?? path22.join(conf
25966
26102
  }
25967
26103
  const prefix = monthPrefix();
25968
26104
  const featuresDir = path22.join(repoPath, "features");
25969
- const existing = existsSync14(featuresDir) ? readdirSync7(featuresDir).find((d) => new RegExp(`^20\\d{2}-\\d{2}-${slug}$`).test(d)) : undefined;
26105
+ const existing = existsSync14(featuresDir) ? readdirSync8(featuresDir).find((d) => new RegExp(`^20\\d{2}-\\d{2}-${slug}$`).test(d)) : undefined;
25970
26106
  const targetDir = path22.join(featuresDir, existing ?? `${prefix}-${slug}`);
25971
26107
  mkdirSync9(targetDir, { recursive: true });
25972
26108
  const files = ["spec.md"];
@@ -26111,7 +26247,7 @@ var init_templates = __esm(() => {
26111
26247
  });
26112
26248
 
26113
26249
  // packages/workit-core/src/core/rules.ts
26114
- import { existsSync as existsSync17, mkdirSync as mkdirSync11, readFileSync as readFileSync18, readdirSync as readdirSync8, writeFileSync as writeFileSync11 } from "node:fs";
26250
+ import { existsSync as existsSync17, mkdirSync as mkdirSync11, readFileSync as readFileSync18, readdirSync as readdirSync9, writeFileSync as writeFileSync11 } from "node:fs";
26115
26251
  import path25 from "node:path";
26116
26252
  var rulesDir = () => path25.join(configDir(), "rules"), parseRule = (markdown) => {
26117
26253
  const fm = markdown.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
@@ -26141,7 +26277,7 @@ var rulesDir = () => path25.join(configDir(), "rules"), parseRule = (markdown) =
26141
26277
  const result = [];
26142
26278
  const dir = rulesDir();
26143
26279
  if (existsSync17(dir)) {
26144
- for (const entry of readdirSync8(dir)) {
26280
+ for (const entry of readdirSync9(dir)) {
26145
26281
  const file = path25.join(dir, entry, "rule.md");
26146
26282
  if (!existsSync17(file))
26147
26283
  continue;
@@ -26264,7 +26400,7 @@ import {
26264
26400
  mkdirSync as mkdirSync12,
26265
26401
  mkdtempSync,
26266
26402
  readFileSync as readFileSync19,
26267
- readdirSync as readdirSync9,
26403
+ readdirSync as readdirSync10,
26268
26404
  renameSync as renameSync3,
26269
26405
  rmSync as rmSync3,
26270
26406
  statSync as statSync9,
@@ -26849,7 +26985,7 @@ async function postUpdate({
26849
26985
  postedComment: true,
26850
26986
  loggedMinutes: 0,
26851
26987
  error: time3.error,
26852
- retry: "workflow_youtrack_log_time"
26988
+ retry: "workit_youtrack_log_time"
26853
26989
  };
26854
26990
  }
26855
26991
  return { ok: true, issueId, postedComment: true, loggedMinutes: minutes };
@@ -27523,7 +27659,7 @@ var logger, readServerVersion = () => {
27523
27659
  }
27524
27660
  });
27525
27661
  }, changelogCategorySchema, lifecycleTool = (action, description) => {
27526
- registerTool(`workflow_plan_${action}`, {
27662
+ registerTool(`workit_plan_${action}`, {
27527
27663
  description,
27528
27664
  inputSchema: {
27529
27665
  plan_path: exports_external.string(),
@@ -27603,7 +27739,7 @@ var init_server3 = __esm(async () => {
27603
27739
  name: "workit",
27604
27740
  version: VERSION
27605
27741
  });
27606
- registerTool("workflow_verify", {
27742
+ registerTool("workit_verify", {
27607
27743
  description: "Run project validation scripts (verify-project.sh). Defaults to Cursor workspace; pass workspace_root when the target repo differs.",
27608
27744
  inputSchema: {
27609
27745
  dry_run: exports_external.boolean().optional(),
@@ -27620,7 +27756,7 @@ var init_server3 = __esm(async () => {
27620
27756
  workspace_root: cwd
27621
27757
  }));
27622
27758
  });
27623
- registerTool("workflow_doctor", {
27759
+ registerTool("workit_doctor", {
27624
27760
  description: "Run the offline workit doctor and report installation health. Defaults to Cursor workspace; pass workspace_root when the target repo differs.",
27625
27761
  inputSchema: {
27626
27762
  workspace_root: workspaceRootSchema
@@ -27629,7 +27765,7 @@ var init_server3 = __esm(async () => {
27629
27765
  const report = runDoctor({ host: "cursor", cwd: workspace_root });
27630
27766
  return jsonResult(report);
27631
27767
  });
27632
- registerTool("workflow_pr_context", {
27768
+ registerTool("workit_pr_context", {
27633
27769
  description: "Gather PR-ready repository context. On feature/* or bugfix/*, fetches and fast-forwards develop + current branch before diffing against develop.",
27634
27770
  inputSchema: {
27635
27771
  range: exports_external.string().optional(),
@@ -27693,7 +27829,7 @@ var init_server3 = __esm(async () => {
27693
27829
  stderr: stderr || undefined
27694
27830
  }));
27695
27831
  });
27696
- registerTool("workflow_pr_create", {
27832
+ registerTool("workit_pr_create", {
27697
27833
  description: "Create GitLab MR or GitHub PR via glab/gh using vcs.json — requires confirmed: true",
27698
27834
  inputSchema: {
27699
27835
  confirmed: exports_external.boolean(),
@@ -27721,7 +27857,7 @@ var init_server3 = __esm(async () => {
27721
27857
  }
27722
27858
  return jsonResult(withWorkspace(workspace_root, { ...data }));
27723
27859
  });
27724
- registerTool("workflow_changelog_context", {
27860
+ registerTool("workit_changelog_context", {
27725
27861
  description: "Gather changelog update context. Defaults to Cursor workspace; pass workspace_root when the target repo differs.",
27726
27862
  inputSchema: {
27727
27863
  range: exports_external.string().optional(),
@@ -27738,7 +27874,7 @@ var init_server3 = __esm(async () => {
27738
27874
  diff_stat: sections["Diff Stat"] ?? "",
27739
27875
  files: sections["Changed Files"] ?? "",
27740
27876
  unreleased,
27741
- apply_hint: "ALWAYS merge via workflow_changelog_apply — never hand-edit ### Added/Changed/… under [Unreleased].",
27877
+ apply_hint: "ALWAYS merge via workit_changelog_apply — never hand-edit ### Added/Changed/… under [Unreleased].",
27742
27878
  workspace_root: cwd,
27743
27879
  stdout,
27744
27880
  exitCode,
@@ -27753,7 +27889,7 @@ var init_server3 = __esm(async () => {
27753
27889
  "Fixed",
27754
27890
  "Security"
27755
27891
  ]);
27756
- registerTool("workflow_changelog_apply", {
27892
+ registerTool("workit_changelog_apply", {
27757
27893
  description: "Merge Keep a Changelog bullets into ## [Unreleased] under the correct ### category. Collapses duplicate category headings. NEVER append a second ### Added block.",
27758
27894
  inputSchema: {
27759
27895
  entries: exports_external.union([
@@ -27781,7 +27917,7 @@ var init_server3 = __esm(async () => {
27781
27917
  unreleased: changelogUnreleasedStats(workspace_root, changelogPath)
27782
27918
  }));
27783
27919
  });
27784
- registerTool("workflow_release_notes_context", {
27920
+ registerTool("workit_release_notes_context", {
27785
27921
  description: "Gather release notes context. Defaults to Cursor workspace; pass workspace_root when the target repo differs.",
27786
27922
  inputSchema: {
27787
27923
  range_or_tag: exports_external.string().min(1),
@@ -27805,7 +27941,7 @@ var init_server3 = __esm(async () => {
27805
27941
  stderr: stderr || undefined
27806
27942
  }));
27807
27943
  });
27808
- registerTool("workflow_docs_context", {
27944
+ registerTool("workit_docs_context", {
27809
27945
  description: "Gather docs refresh context. Defaults to Cursor workspace; pass workspace_root when the target repo differs.",
27810
27946
  inputSchema: {
27811
27947
  range: exports_external.string().optional(),
@@ -27825,7 +27961,7 @@ var init_server3 = __esm(async () => {
27825
27961
  stderr: stderr || undefined
27826
27962
  }));
27827
27963
  });
27828
- registerTool("workflow_git_context", {
27964
+ registerTool("workit_git_context", {
27829
27965
  description: "Gather git status for commit skill. Defaults to Cursor workspace; pass workspace_root when the target repo differs.",
27830
27966
  inputSchema: {
27831
27967
  paths: exports_external.array(exports_external.string()).optional(),
@@ -27835,7 +27971,7 @@ var init_server3 = __esm(async () => {
27835
27971
  const data = gitContext(workspace_root, paths ?? []);
27836
27972
  return jsonResult(withWorkspace(workspace_root, data));
27837
27973
  });
27838
- registerTool("workflow_resolve_branch", {
27974
+ registerTool("workit_resolve_branch", {
27839
27975
  description: "Resolve feature/* or bugfix/* branch from spec/plan. Returns current_branch, dirty, needs_checkout. No worktrees.",
27840
27976
  inputSchema: {
27841
27977
  spec_path: exports_external.string(),
@@ -27848,7 +27984,7 @@ var init_server3 = __esm(async () => {
27848
27984
  return jsonResult({ error: data.error });
27849
27985
  return jsonResult(withWorkspace(workspace_root, data));
27850
27986
  });
27851
- registerTool("workflow_branch_setup", {
27987
+ registerTool("workit_branch_setup", {
27852
27988
  description: "In-place checkout of feature/* or bugfix/* branch. Stash required when dirty. NEVER uses worktrees.",
27853
27989
  inputSchema: {
27854
27990
  action: exports_external.enum(["setup", "reapply_stash"]).optional(),
@@ -27869,7 +28005,7 @@ var init_server3 = __esm(async () => {
27869
28005
  return jsonResult({ error: data.error });
27870
28006
  return jsonResult(withWorkspace(workspace_root, data));
27871
28007
  });
27872
- registerTool("workflow_sdd_context", {
28008
+ registerTool("workit_sdd_context", {
27873
28009
  description: "Resolve canonical docs/<slug>/sdd/ paths; creates nothing (progress.md appears only on the first confirmed append). NEVER use .superpowers/sdd.",
27874
28010
  inputSchema: {
27875
28011
  slug: exports_external.string().optional(),
@@ -27882,7 +28018,7 @@ var init_server3 = __esm(async () => {
27882
28018
  return jsonResult({ error: data.error });
27883
28019
  return jsonResult(withWorkspace(workspace_root, data));
27884
28020
  });
27885
- registerTool("workflow_sdd_task_brief", {
28021
+ registerTool("workit_sdd_task_brief", {
27886
28022
  description: "Write task-N-brief.md under docs/<slug>/sdd/",
27887
28023
  inputSchema: {
27888
28024
  sdd_dir: exports_external.string(),
@@ -27894,7 +28030,7 @@ var init_server3 = __esm(async () => {
27894
28030
  const slug = slugFromSddPath(sdd_dir);
27895
28031
  if (!slug)
27896
28032
  return jsonResult({ error: "could not derive slug — expected docs/<slug>/sdd/..." });
27897
- const gate = assertProductGates(workspace_root, slug, { requireMenu: true, requireDocs: true }, cursorMutationContext(workspace_root));
28033
+ const gate = assertSddControlGates(workspace_root, slug, { requireMenu: true, requireDocs: true }, cursorMutationContext(workspace_root));
27898
28034
  if (!gate.ok)
27899
28035
  return jsonResult({ error: gate.error, code: gate.code });
27900
28036
  const data = sddTaskBrief({
@@ -27905,7 +28041,7 @@ var init_server3 = __esm(async () => {
27905
28041
  });
27906
28042
  return jsonResult(withWorkspace(workspace_root, data));
27907
28043
  });
27908
- registerTool("workflow_sdd_review_package", {
28044
+ registerTool("workit_sdd_review_package", {
27909
28045
  description: "Write review diff under SDD dir between base and head SHAs",
27910
28046
  inputSchema: {
27911
28047
  sdd_dir: exports_external.string(),
@@ -27917,7 +28053,7 @@ var init_server3 = __esm(async () => {
27917
28053
  const slug = slugFromSddPath(sdd_dir);
27918
28054
  if (!slug)
27919
28055
  return jsonResult({ error: "could not derive slug — expected docs/<slug>/sdd/..." });
27920
- const gate = assertProductGates(workspace_root, slug, { requireMenu: true, requireDocs: true }, cursorMutationContext(workspace_root));
28056
+ const gate = assertSddControlGates(workspace_root, slug, { requireMenu: true, requireDocs: true }, cursorMutationContext(workspace_root));
27921
28057
  if (!gate.ok)
27922
28058
  return jsonResult({ error: gate.error, code: gate.code });
27923
28059
  const data = sddReviewPackage({
@@ -27930,7 +28066,7 @@ var init_server3 = __esm(async () => {
27930
28066
  return jsonResult({ error: data.error });
27931
28067
  return jsonResult(withWorkspace(workspace_root, data));
27932
28068
  });
27933
- registerTool("workflow_sdd_append_progress", {
28069
+ registerTool("workit_sdd_append_progress", {
27934
28070
  description: "Append one validated line to docs/<slug>/sdd/progress.md",
27935
28071
  inputSchema: {
27936
28072
  progress_path: exports_external.string(),
@@ -27941,7 +28077,7 @@ var init_server3 = __esm(async () => {
27941
28077
  const slug = slugFromSddPath(progress_path);
27942
28078
  if (!slug)
27943
28079
  return jsonResult({ error: "could not derive slug — expected docs/<slug>/sdd/..." });
27944
- const gate = assertProductGates(workspace_root, slug, { requireMenu: true, requireDocs: true }, cursorMutationContext(workspace_root));
28080
+ const gate = assertSddControlGates(workspace_root, slug, { requireMenu: true, requireDocs: true }, cursorMutationContext(workspace_root));
27945
28081
  if (!gate.ok)
27946
28082
  return jsonResult({ error: gate.error, code: gate.code });
27947
28083
  const data = sddAppendProgress({ progress_path, line, workspace_root });
@@ -27949,7 +28085,27 @@ var init_server3 = __esm(async () => {
27949
28085
  return jsonResult({ error: data.error });
27950
28086
  return jsonResult(withWorkspace(workspace_root, data));
27951
28087
  });
27952
- registerTool("workflow_docs_branch", {
28088
+ registerTool("workit_sdd_append_advisory", {
28089
+ description: "Append a validated advisory line to docs/<slug>/sdd/advisories.md (coordinator-owned)",
28090
+ inputSchema: {
28091
+ advisories_path: exports_external.string(),
28092
+ task_id: exports_external.number(),
28093
+ text: exports_external.string(),
28094
+ workspace_root: workspaceRootSchema
28095
+ }
28096
+ }, async ({ advisories_path, task_id, text, workspace_root }) => {
28097
+ const slug = slugFromSddPath(advisories_path);
28098
+ if (!slug)
28099
+ return jsonResult({ error: "could not derive slug — expected docs/<slug>/sdd/..." });
28100
+ const gate = assertSddControlGates(workspace_root, slug, { requireMenu: true, requireDocs: true }, cursorMutationContext(workspace_root));
28101
+ if (!gate.ok)
28102
+ return jsonResult({ error: gate.error, code: gate.code });
28103
+ const data = sddAppendAdvisory({ advisories_path, task_id, text, workspace_root });
28104
+ if ("error" in data)
28105
+ return jsonResult({ error: data.error, code: data.code });
28106
+ return jsonResult(withWorkspace(workspace_root, data));
28107
+ });
28108
+ registerTool("workit_docs_branch", {
27953
28109
  description: "Resolve branch for spec/plan authors: keep current feature|bugfix or create from the configured base.",
27954
28110
  inputSchema: {
27955
28111
  plan_path: exports_external.string().optional(),
@@ -27962,7 +28118,7 @@ var init_server3 = __esm(async () => {
27962
28118
  return jsonResult(withWorkspace(workspace_root, { error: data.error }));
27963
28119
  return jsonResult(withWorkspace(workspace_root, data));
27964
28120
  });
27965
- registerTool("workflow_docs_layout", {
28121
+ registerTool("workit_docs_layout", {
27966
28122
  description: "Canonical docs layout: prepare creates missing docs/ and docs/<slug>/; migrate detects legacy docs/superpowers/ and copies safe pairs after a native Migrate safely / Not now question",
27967
28123
  inputSchema: {
27968
28124
  action: exports_external.enum(["prepare", "migrate"]).default("prepare"),
@@ -28006,7 +28162,7 @@ var init_server3 = __esm(async () => {
28006
28162
  return jsonResult(withWorkspace(workspace_root, { error: result.error }));
28007
28163
  return jsonResult(withWorkspace(workspace_root, result));
28008
28164
  });
28009
- registerTool("workflow_docs_validate", {
28165
+ registerTool("workit_docs_validate", {
28010
28166
  description: "Hard-fail validate spec/plan headers, link, branch, task order; returns quality findings (hard/warning). Defaults to Cursor workspace; pass workspace_root when paths are relative to another repo.",
28011
28167
  inputSchema: {
28012
28168
  spec_path: exports_external.string(),
@@ -28020,7 +28176,7 @@ var init_server3 = __esm(async () => {
28020
28176
  }
28021
28177
  return jsonResult(withWorkspace(workspace_root, data));
28022
28178
  });
28023
- registerTool("workflow_plan_tasks", {
28179
+ registerTool("workit_plan_tasks", {
28024
28180
  description: "Parse plan ### Task N sections into structured tasks with section_text. Defaults to Cursor workspace; pass workspace_root when paths are relative to another repo.",
28025
28181
  inputSchema: {
28026
28182
  plan_path: exports_external.string(),
@@ -28044,7 +28200,7 @@ var init_server3 = __esm(async () => {
28044
28200
  }
28045
28201
  return jsonResult(withWorkspace(workspace_root, data));
28046
28202
  });
28047
- registerTool("workflow_handoff_prompt", {
28203
+ registerTool("workit_handoff_prompt", {
28048
28204
  description: "Build copy-paste handoff prompt for next session. Defaults to Cursor workspace; pass workspace_root when spec/plan paths are relative to another repo.",
28049
28205
  inputSchema: {
28050
28206
  message: exports_external.string(),
@@ -28232,7 +28388,7 @@ var init_server3 = __esm(async () => {
28232
28388
  return jsonResult({ error: data.error });
28233
28389
  return jsonResult(data.data);
28234
28390
  });
28235
- registerTool("workflow_youtrack_verify_token", {
28391
+ registerTool("workit_youtrack_verify_token", {
28236
28392
  description: "Read-only YouTrack token test (GET /api/users/me). No work items created.",
28237
28393
  inputSchema: {}
28238
28394
  }, async () => {
@@ -28244,7 +28400,7 @@ var init_server3 = __esm(async () => {
28244
28400
  return jsonResult({ error: data.error ?? "token invalid", ...data });
28245
28401
  return jsonResult(data);
28246
28402
  });
28247
- registerTool("workflow_youtrack_parse_issue", {
28403
+ registerTool("workit_youtrack_parse_issue", {
28248
28404
  description: "Parse YouTrack issue URL or bare id (e.g. NSR-40) into issueId",
28249
28405
  inputSchema: {
28250
28406
  issue_ref: exports_external.string().describe("YouTrack URL or issue id, e.g. https://…/issue/NSR-40 or NSR-40")
@@ -28255,7 +28411,7 @@ var init_server3 = __esm(async () => {
28255
28411
  return jsonResult({ error: data.error });
28256
28412
  return jsonResult(data);
28257
28413
  });
28258
- registerTool("workflow_youtrack_context", {
28414
+ registerTool("workit_youtrack_context", {
28259
28415
  description: "YouTrack config, greeting, issue resolution (from issue_url/id or meetings)",
28260
28416
  inputSchema: {
28261
28417
  mode: exports_external.enum(["meetings", "task"]).optional(),
@@ -28284,7 +28440,7 @@ var init_server3 = __esm(async () => {
28284
28440
  }
28285
28441
  return jsonResult(withWorkspace(workspace_root, data));
28286
28442
  });
28287
- registerTool("workflow_youtrack_parse_duration", {
28443
+ registerTool("workit_youtrack_parse_duration", {
28288
28444
  description: "Parse duration text (e.g. 1h 30m) to integer minutes",
28289
28445
  inputSchema: {
28290
28446
  text: exports_external.string(),
@@ -28296,7 +28452,7 @@ var init_server3 = __esm(async () => {
28296
28452
  return jsonResult({ error: data.error });
28297
28453
  return jsonResult(withWorkspace(workspace_root, data));
28298
28454
  });
28299
- registerTool("workflow_youtrack_log_time", {
28455
+ registerTool("workit_youtrack_log_time", {
28300
28456
  description: "POST YouTrack work item (time only, no comment)",
28301
28457
  inputSchema: {
28302
28458
  issueId: exports_external.string(),
@@ -28317,7 +28473,7 @@ var init_server3 = __esm(async () => {
28317
28473
  return jsonResult({ error: data.error });
28318
28474
  return jsonResult(withWorkspace(workspace_root, data));
28319
28475
  });
28320
- registerTool("workflow_youtrack_draft", {
28476
+ registerTool("workit_youtrack_draft", {
28321
28477
  description: "Build ES-CL comment markdown without posting (envelope only by default)",
28322
28478
  inputSchema: {
28323
28479
  issueId: exports_external.string(),
@@ -28329,7 +28485,7 @@ var init_server3 = __esm(async () => {
28329
28485
  facts: exports_external.record(exports_external.any()).optional()
28330
28486
  }
28331
28487
  }, async (input) => jsonResult(buildDraft(input)));
28332
- registerTool("workflow_youtrack_post", {
28488
+ registerTool("workit_youtrack_post", {
28333
28489
  description: "Post YouTrack comment and optional time — requires confirmed: true",
28334
28490
  inputSchema: {
28335
28491
  confirmed: exports_external.boolean(),
@@ -28350,7 +28506,7 @@ var init_server3 = __esm(async () => {
28350
28506
  return jsonResult({ error: data.error });
28351
28507
  return jsonResult(withWorkspace(workspace_root, data));
28352
28508
  });
28353
- registerTool("workflow_present_ascii", {
28509
+ registerTool("workit_present_ascii", {
28354
28510
  description: "Render deterministic ASCII UI wireframe from JSON spec",
28355
28511
  inputSchema: {
28356
28512
  title: exports_external.string().optional(),
@@ -28363,7 +28519,7 @@ var init_server3 = __esm(async () => {
28363
28519
  return jsonResult({ error: data.error });
28364
28520
  return jsonResult(data.data);
28365
28521
  });
28366
- registerTool("workflow_present_flow", {
28522
+ registerTool("workit_present_flow", {
28367
28523
  description: "Render mermaid flowchart from JSON nodes/edges",
28368
28524
  inputSchema: {
28369
28525
  title: exports_external.string().optional(),
@@ -28385,7 +28541,7 @@ var init_server3 = __esm(async () => {
28385
28541
  return jsonResult({ error: data.error });
28386
28542
  return jsonResult(data.data);
28387
28543
  });
28388
- registerTool("workflow_flow_status", {
28544
+ registerTool("workit_flow_status", {
28389
28545
  description: "Read the spec/plan approval flow state for a workflow; on first read it records flow activation and canonical document paths (FG-01)",
28390
28546
  inputSchema: {
28391
28547
  plan_path: exports_external.string().optional(),
@@ -28421,7 +28577,7 @@ var init_server3 = __esm(async () => {
28421
28577
  flow_path: `docs/${slug}/sdd/flow.json`
28422
28578
  });
28423
28579
  });
28424
- registerTool("workflow_spec_approve", {
28580
+ registerTool("workit_spec_approve", {
28425
28581
  description: "Advance spec status with the Cursor policy-only confirmation: draft -> approved in a single call. The self-review validation runs automatically inside the transition; only the final approval asks for your confirmation. Cursor records attested: false (the MCP cannot observe AskQuestion results); there is no evidence argument (CA-42).",
28426
28582
  inputSchema: {
28427
28583
  spec_path: exports_external.string(),
@@ -28437,7 +28593,7 @@ var init_server3 = __esm(async () => {
28437
28593
  return jsonResult({ error: result.error, code: result.code });
28438
28594
  return jsonResult({ spec: spec_path, status: readFlowState(workspace, slug).spec.status });
28439
28595
  });
28440
- registerTool("workflow_plan_approve", {
28596
+ registerTool("workit_plan_approve", {
28441
28597
  description: "Advance plan status with the Cursor policy-only confirmation: draft -> approved in a single call. The self-review validation runs automatically inside the transition; only the final approval asks for your confirmation. Requires approved spec. Cursor records attested: false; there is no evidence argument (CA-42).",
28442
28598
  inputSchema: {
28443
28599
  plan_path: exports_external.string(),
@@ -28453,7 +28609,7 @@ var init_server3 = __esm(async () => {
28453
28609
  return jsonResult({ error: result.error, code: result.code });
28454
28610
  return jsonResult({ plan: plan_path, status: readFlowState(workspace, slug).plan.status });
28455
28611
  });
28456
- registerTool("workflow_plan_menu", {
28612
+ registerTool("workit_plan_menu", {
28457
28613
  description: "Record the answered post-plan choice menu with the Cursor policy-only confirmation. subagent-driven is rejected as unsupported on Cursor (CA-42); there is no evidence argument.",
28458
28614
  inputSchema: {
28459
28615
  plan_path: exports_external.string(),
@@ -28473,7 +28629,7 @@ var init_server3 = __esm(async () => {
28473
28629
  lifecycleTool("pause", "Pause a running plan with the Cursor policy-only confirmation: active -> paused. The MCP cannot observe AskQuestion results, so it records attested: false; there is no evidence argument (CA-42). Requires plan_path and workspace_root.");
28474
28630
  lifecycleTool("resume", "Resume a paused plan with the Cursor policy-only confirmation: paused -> active. The MCP cannot observe AskQuestion results, so it records attested: false; there is no evidence argument (CA-42). Requires plan_path and workspace_root.");
28475
28631
  lifecycleTool("complete", "Complete a running plan with the Cursor policy-only confirmation: active/paused -> completed, after the SDD ledger is complete and repository verification passes. The MCP cannot observe AskQuestion results, so it records attested: false; there is no evidence argument (CA-42). Requires plan_path and workspace_root.");
28476
- registerTool("workflow_docs_repo_link", {
28632
+ registerTool("workit_docs_repo_link", {
28477
28633
  description: "Link the component docs repo in the toolkit config",
28478
28634
  inputSchema: {
28479
28635
  path: exports_external.string(),
@@ -28485,11 +28641,11 @@ var init_server3 = __esm(async () => {
28485
28641
  return jsonResult({ error: result.error });
28486
28642
  return jsonResult({ path: result.path });
28487
28643
  });
28488
- registerTool("workflow_docs_list", {
28644
+ registerTool("workit_docs_list", {
28489
28645
  description: "List local specs with docs-repo promotion status",
28490
28646
  inputSchema: { workspace_root: workspaceRootSchema }
28491
28647
  }, async ({ workspace_root }) => jsonResult(listSpecs(workspace_root)));
28492
- registerTool("workflow_docs_promote", {
28648
+ registerTool("workit_docs_promote", {
28493
28649
  description: "Promote a spec (+plan) to the linked docs repo with quality gate",
28494
28650
  inputSchema: {
28495
28651
  slug: exports_external.string(),
@@ -28507,11 +28663,11 @@ var init_server3 = __esm(async () => {
28507
28663
  index_updated: result.index_updated
28508
28664
  });
28509
28665
  });
28510
- registerTool("workflow_template_list", {
28666
+ registerTool("workit_template_list", {
28511
28667
  description: "List editable templates with their source",
28512
28668
  inputSchema: { workspace_root: workspaceRootSchema }
28513
28669
  }, async () => jsonResult({ templates: listTemplates() }));
28514
- registerTool("workflow_template_edit", {
28670
+ registerTool("workit_template_edit", {
28515
28671
  description: "Write an edited template to the toolkit config dir",
28516
28672
  inputSchema: {
28517
28673
  name: exports_external.enum(["issue-update", "greeting", "headers"]),
@@ -28524,11 +28680,11 @@ var init_server3 = __esm(async () => {
28524
28680
  return jsonResult({ error: result.error });
28525
28681
  return jsonResult({ path: result.path });
28526
28682
  });
28527
- registerTool("workflow_rule_list", {
28683
+ registerTool("workit_rule_list", {
28528
28684
  description: "List canonical rules (config) with platforms",
28529
28685
  inputSchema: { workspace_root: workspaceRootSchema }
28530
28686
  }, async () => jsonResult({ rules: listRules() }));
28531
- registerTool("workflow_rule_edit", {
28687
+ registerTool("workit_rule_edit", {
28532
28688
  description: "Write a canonical rule to the toolkit config dir",
28533
28689
  inputSchema: {
28534
28690
  name: exports_external.string(),