@dosu/cli 0.66.1 → 0.67.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/bin/dosu.js +80 -25
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -119,7 +119,7 @@ Once authenticated against a deployment, you can drive the Dosu platform without
119
119
  | `dosu knowledge` | Search and browse your knowledge base |
120
120
  | `dosu docs` | Manage documents (list, create, update, import, publish) |
121
121
  | `dosu threads` | List and manage conversation threads |
122
- | `dosu review` | Document review workflow, plus `review notifications` to route a Library's or Agent's reviews to a Slack channel |
122
+ | `dosu review` | Document review workflow for the selected Library, plus `review notifications` to route a Library's or Agent's reviews to a Slack channel |
123
123
  | `dosu sources` | Manage connected data sources (list, connect, create, sync, update) |
124
124
  | `dosu integrations` | List and inspect platform integrations (Slack, GitHub, …) |
125
125
  | `dosu topics` | List knowledge base topics and their pages |
package/bin/dosu.js CHANGED
@@ -1083,7 +1083,7 @@ function isNpxInvocation(channel = INSTALL_CHANNEL, env = process.env) {
1083
1083
  function getVersionString() {
1084
1084
  return `v${VERSION}`;
1085
1085
  }
1086
- var VERSION = "0.66.1", INSTALL_CHANNEL = "npm";
1086
+ var VERSION = "0.67.0", INSTALL_CHANNEL = "npm";
1087
1087
 
1088
1088
  // src/debug/logger.ts
1089
1089
  import {
@@ -11535,6 +11535,7 @@ ${import_picocolors15.default.dim(`Current: ${cfg.active_account?.target?.deploy
11535
11535
  return;
11536
11536
  }
11537
11537
  console.log(import_picocolors15.default.green(`Switched to deployment: ${deployment.name}`));
11538
+ console.log(import_picocolors15.default.dim("This changes the CLI's saved selection. An AI tool with a running Dosu MCP connection " + "keeps its previous deployment until you run 'dosu mcp refresh' and restart or " + "reconnect it."));
11538
11539
  });
11539
11540
  return cmd;
11540
11541
  }
@@ -14289,7 +14290,7 @@ var init_conflicts = __esm(() => {
14289
14290
  });
14290
14291
 
14291
14292
  // src/telemetry/debug-id.ts
14292
- var BUNDLE_DEBUG_ID_PLACEHOLDER = "0891ed1f-f060-16b6-6475-6e2164756e21";
14293
+ var BUNDLE_DEBUG_ID_PLACEHOLDER = "5d3e9365-4283-2b42-6475-6e2164756e21";
14293
14294
 
14294
14295
  // src/telemetry/telemetry.ts
14295
14296
  import { randomUUID as randomUUID2 } from "node:crypto";
@@ -60386,17 +60387,58 @@ function printDraftPreview(draft) {
60386
60387
  console.log();
60387
60388
  console.log(draft.body ?? "");
60388
60389
  }
60389
- async function getKnowledgeStoreId2(client, spaceId) {
60390
- const store = await client.knowledgeStore.getBySpaceId.query({ space_id: spaceId });
60391
- if (!store) {
60392
- console.error(import_picocolors27.default.red("No knowledge store found for this deployment."));
60393
- process.exit(1);
60390
+ function failScope(message, hint = SELECT_LIBRARY_HINT) {
60391
+ console.error(import_picocolors27.default.red(message));
60392
+ console.error(import_picocolors27.default.dim(hint));
60393
+ process.exit(1);
60394
+ }
60395
+ async function lookupLibrary(client, spaceId) {
60396
+ try {
60397
+ const library = await client.libraries.info.query(spaceId);
60398
+ return { found: true, name: library.name || null };
60399
+ } catch (err) {
60400
+ if (isNotFound(err))
60401
+ return { found: false };
60402
+ return { found: true, name: null };
60394
60403
  }
60395
- return store.id;
60404
+ }
60405
+ async function resolveReviewScope(client, spaceId, deploymentId) {
60406
+ const [store, library, deployment] = await Promise.all([
60407
+ client.knowledgeStore.getBySpaceId.query({ space_id: spaceId }),
60408
+ lookupLibrary(client, spaceId),
60409
+ deploymentId ? client.workspaces.get.query(deploymentId) : Promise.resolve(undefined)
60410
+ ]);
60411
+ if (deploymentId && !deployment) {
60412
+ failScope(`The selected MCP deployment (${deploymentId}) is unavailable: it was deleted, or the ` + "signed-in account cannot access it.");
60413
+ }
60414
+ if (deployment && deployment.space_id !== spaceId) {
60415
+ failScope(`The saved Library (${spaceId}) does not match the Library of the selected MCP ` + `deployment (${deployment.space_id}).`, `Run 'dosu deployments switch ${deployment.deployment_id}' to save that deployment's ` + "Library again, or choose another MCP deployment with 'dosu deployments list'.");
60416
+ }
60417
+ if (!library.found || !store) {
60418
+ failScope(`The selected Library (${spaceId}) is unavailable: it was deleted, or the signed-in ` + "account cannot access it.");
60419
+ }
60420
+ return {
60421
+ knowledgeStoreId: store.id,
60422
+ library: { id: spaceId, name: library.name },
60423
+ deployment: deployment ? { id: deployment.deployment_id, name: deployment.name || null } : null
60424
+ };
60425
+ }
60426
+ function describeScopeEntry(entry) {
60427
+ return entry.name ? `${entry.name} (${entry.id})` : entry.id;
60428
+ }
60429
+ function printScope(scope) {
60430
+ printInfo([
60431
+ ["Library", describeScopeEntry(scope.library)],
60432
+ [
60433
+ "MCP deployment",
60434
+ scope.deployment ? describeScopeEntry(scope.deployment) : "none selected (draft replies not listed)"
60435
+ ]
60436
+ ]);
60437
+ console.log();
60396
60438
  }
60397
60439
  function reviewCommand() {
60398
60440
  const cmd = new Command("review").description("Review workflow (doc changes and draft replies)");
60399
- cmd.command("list").description("List pending review items (doc changes and draft replies)").addOption(new Option("--since <when>", "Only items created at or after <when>: a duration back from now (24h, 7d, 2w), " + "a UTC date (2026-09-01), or an ISO-8601 datetime").argParser(timeBound)).addOption(new Option("--until <when>", "Only items created before <when> (same forms; a date includes that whole day)").argParser(timeBound)).option("--json", "Output as JSON").action(async (opts) => {
60441
+ cmd.command("list").description("List pending review items in the selected Library (doc changes and draft replies)").addOption(new Option("--since <when>", "Only items created at or after <when>: a duration back from now (24h, 7d, 2w), " + "a UTC date (2026-09-01), or an ISO-8601 datetime").argParser(timeBound)).addOption(new Option("--until <when>", "Only items created before <when> (same forms; a date includes that whole day)").argParser(timeBound)).option("--json", "Output as JSON").action(async (opts) => {
60400
60442
  let range;
60401
60443
  try {
60402
60444
  range = resolveTimeRange(opts.since, opts.until);
@@ -60407,25 +60449,36 @@ function reviewCommand() {
60407
60449
  const rangeLabel = describeTimeRange(range);
60408
60450
  const inRange = rangeLabel ? ` ${rangeLabel}` : "";
60409
60451
  const cfg = requireConfig10();
60410
- if (!cfg.active_account?.target?.space_id) {
60411
- console.error(import_picocolors27.default.red("Missing space config. Run 'dosu setup' to reconfigure."));
60412
- process.exit(1);
60452
+ const target = cfg.active_account?.target;
60453
+ if (!target?.space_id) {
60454
+ failScope("No Library selected. The review list reads the Library of the selected MCP deployment.");
60413
60455
  }
60414
60456
  const client = createTypedClient(cfg);
60415
- const ksId = await getKnowledgeStoreId2(client, cfg.active_account?.target?.space_id);
60457
+ const scope = await resolveReviewScope(client, target.space_id, target.deployment_id);
60416
60458
  const result = await client.review.listPending.query({
60417
- knowledgeStoreId: ksId,
60418
- deploymentId: cfg.active_account?.target?.deployment_id,
60459
+ knowledgeStoreId: scope.knowledgeStoreId,
60460
+ ...scope.deployment && { deploymentId: scope.deployment.id },
60419
60461
  ...range.since && { since: range.since.toISOString() },
60420
60462
  ...range.until && { until: range.until.toISOString() }
60421
60463
  });
60422
60464
  const { items, truncated, total } = result;
60423
60465
  if (opts.json) {
60424
- printResult(result, opts);
60466
+ printResult({
60467
+ ...result,
60468
+ scope: {
60469
+ library: scope.library,
60470
+ deployment: scope.deployment,
60471
+ kinds: scope.deployment ? ["doc_change", "draft_message"] : ["doc_change"],
60472
+ since: range.since?.toISOString() ?? null,
60473
+ until: range.until?.toISOString() ?? null
60474
+ }
60475
+ }, opts);
60425
60476
  return;
60426
60477
  }
60478
+ printScope(scope);
60427
60479
  if (!items || items.length === 0) {
60428
- console.log(import_picocolors27.default.dim(`No pending review items${inRange}.`));
60480
+ console.log(import_picocolors27.default.dim(`No pending review items in this scope${inRange}.`));
60481
+ console.log(import_picocolors27.default.dim("Only the selected Library is listed. To review another Library, find its MCP " + "deployment with 'dosu deployments list' and select it with " + "'dosu deployments switch <deployment-id>'."));
60429
60482
  return;
60430
60483
  }
60431
60484
  if (rangeLabel)
@@ -60617,7 +60670,7 @@ function reviewCommand() {
60617
60670
  cmd.addCommand(reviewNotificationsCommand());
60618
60671
  return cmd;
60619
60672
  }
60620
- var import_picocolors27, DRAFT_MESSAGE_ID_PREFIX = "draft_message:";
60673
+ var import_picocolors27, DRAFT_MESSAGE_ID_PREFIX = "draft_message:", SELECT_LIBRARY_HINT;
60621
60674
  var init_review = __esm(() => {
60622
60675
  init_dist();
60623
60676
  init_commander();
@@ -60628,6 +60681,7 @@ var init_review = __esm(() => {
60628
60681
  init_review_notifications();
60629
60682
  init_time_range();
60630
60683
  import_picocolors27 = __toESM(require_picocolors(), 1);
60684
+ SELECT_LIBRARY_HINT = "Run 'dosu deployments list' to see the MCP deployments you can select, then " + "'dosu deployments switch <deployment-id>' for the Library to review, or run 'dosu setup' " + "to choose the organization and Library again.";
60631
60685
  });
60632
60686
 
60633
60687
  // src/generated/skills.ts
@@ -61089,7 +61143,7 @@ dosu review notifications set (--library <library-id> | --agent <agent-id>)
61089
61143
  dosu review notifications clear (--library <library-id> | --agent <agent-id>) [--confirm] [--json]
61090
61144
  \`\`\`
61091
61145
 
61092
- - \`list\` reads the selected Library's pending doc changes plus the selected MCP deployment's draft replies. JSON is \`{items, truncated, total}\`: at most 50 items, newest first; \`total\` is a lower bound when \`truncated\` is true. \`--since\`/\`--until\` take \`24h\`/\`7d\`/\`2w\`, a UTC date, or an ISO-8601 datetime.
61146
+ - \`list\` reads the selected Library's pending doc changes plus the selected MCP deployment's draft replies. JSON is \`{items, truncated, total, scope}\`: at most 50 items, newest first; \`total\` is a lower bound when \`truncated\` is true; \`scope\` names the Library and MCP deployment searched (see [review-workflow.md](review-workflow.md)). A missing, deleted, or inaccessible Library or deployment is an error, not an empty list. \`--since\`/\`--until\` take \`24h\`/\`7d\`/\`2w\`, a UTC date, or an ISO-8601 datetime.
61093
61147
  - IDs are opaque: pass each \`id\` from \`list\` verbatim (draft replies carry a \`draft_message:\` prefix). \`revert\` takes a decided doc change's page-version ID and does not apply to drafts.
61094
61148
  - \`edit\` requires at least one field; drafts accept only \`--body\`/\`--body-file\`. \`approve\` and \`reject\` do not write without interactive confirmation or \`--confirm\`.
61095
61149
  - \`notifications\` manages the Slack channel that receives review notifications for one Library (doc reviews) or one Agent (its draft replies). Unlike the queue commands it takes an explicit target, not the selected MCP deployment. Pass exactly one of \`--library\`/\`--agent\` (UUID v4; Agent IDs come from \`dosu agents list\`).
@@ -61169,6 +61223,7 @@ dosu deployments switch <id> [--json]
61169
61223
 
61170
61224
  dosu mcp list
61171
61225
  dosu mcp add <agent> [--global] [--show-secret]
61226
+ dosu mcp refresh
61172
61227
  dosu skill install | remove | update
61173
61228
  dosu telemetry status [--json]
61174
61229
  dosu telemetry enable | disable | reset
@@ -61177,7 +61232,7 @@ dosu upgrade [--auto on|off]
61177
61232
  dosu logs [--tail [n]] [--clear]
61178
61233
  \`\`\`
61179
61234
 
61180
- \`deployments\` selects the MCP deployment stored in local config; it is distinct from \`agents\`. \`insights\` opens an interactive visual report. \`logs --clear\` deletes the CLI log file. The CLI updates itself in the background by default; a \`[dosu:update] Installing ...\` notice on stderr needs no action. \`upgrade --auto off\` turns that off.
61235
+ \`deployments\` selects the MCP deployment stored in local config; it is distinct from \`agents\`. \`deployments switch\` does not repoint an AI tool's running MCP connection; \`mcp refresh\` rewrites the global Dosu MCP entry of each configured tool from the current selection (project-level entries change on the next \`dosu setup\` or \`dosu mcp add\`), and the tool then needs a restart or reconnect. \`insights\` opens an interactive visual report. \`logs --clear\` deletes the CLI log file. The CLI updates itself in the background by default; a \`[dosu:update] Installing ...\` notice on stderr needs no action. \`upgrade --auto off\` turns that off.
61181
61236
 
61182
61237
  ## Codebase audit
61183
61238
 
@@ -61192,7 +61247,7 @@ The coding agent writes the findings; Dosu generates the selected docs. Follow [
61192
61247
  },
61193
61248
  {
61194
61249
  path: "references/review-workflow.md",
61195
- content: '# Review workflow\n\nHow to work Dosu\'s review queue from the CLI: triage pending items, read the\ndiff, optionally edit, and apply a decision — safely.\n\nThe queue holds **document versions** (AI-generated, user-edited, synced from\nsource, or API-created) and **draft messages**, all surfaced through the same\n`dosu review` commands. Doc changes come from the selected Library; draft\nreplies come only from threads of the selected MCP deployment.\n\n## Read the list result\n\n`dosu review list --json` returns `{ "items": [...], "truncated": <bool>, "total": <n> }`.\n\n- `items` holds at most 50 entries, newest first, doc changes and draft\n replies merged.\n- `truncated: true` means more pending items may exist than `items` shows.\n- `total` counts what the server found before that cap. When `truncated` is\n true it is a lower bound: report "at least `total`", never an exact backlog.\n- Each `id` is opaque. A doc change\'s `id` is its page-version UUID; a draft\n reply\'s `id` looks like `draft_message:<uuid>` and has `kind: "draft_message"`.\n Pass the `id` exactly as listed to `diff`, `edit`, `approve`, and `reject`;\n do not strip the prefix or shorten it.\n- `--since <when>` and `--until <when>` narrow the list by creation time. Each\n takes a duration back from now (`24h`, `7d`, `2w`), a UTC date\n (`2026-09-01`; an `--until` date includes that whole day), or an ISO-8601\n datetime. When `truncated` is true, `--until` reaches older items.\n\nAn empty `items` array means no pending items in the current scope. It is not\na reason to switch deployments.\n\n## Check the context when the scope looks wrong\n\nRun this only when the user says the list is for the wrong Library, names a\ndifferent Library, or a command reports missing context:\n\n1. `dosu status --json`: login state and the selected MCP deployment.\n2. `dosu deployments info --json`: the selected MCP deployment. The list reads\n the Library saved in the CLI\'s config, which `dosu setup` and\n `dosu deployments switch` set to this deployment\'s `space_id`\n (`dosu libraries info <space_id> --json` gives its name).\n3. If that is not the Library the user means, run\n `dosu deployments list --json` and find the MCP deployment whose `space_id`\n matches it (`dosu libraries list --json` maps names to IDs).\n4. Switch only to a deployment the user named or confirmed:\n `dosu deployments switch <deployment-id> --json`. It changes the CLI\'s\n selection for later commands and mints a new API key, so say that it did.\n Never pick the first deployment, and ask when several match or none does.\n5. Run `dosu review list --json` again.\n\n## Draft reply limits\n\n- `edit` on a draft accepts `--body` or `--body-file` only (no `--title`).\n- `approve` publishes the draft to its thread; `reject` discards it.\n- Drafts have no `revert`. A rejected draft is regenerated on the next agent run.\n\n## Scope tool access for a review session\n\nApproving and rejecting are destructive and outward-facing. When you spin up an\nagent session dedicated to reviewing, scope it to just the review commands:\n\n```yaml\nallowed-tools: Bash(dosu review:*)\n```\n\nThis lets the agent triage, diff, and edit, but keeps it from running unrelated\nCLI commands during a review pass.\n\n## The flow\n\n```bash\n# 1. Triage — what\'s pending? Columns: ID, Kind, Title, Source, Status, Created.\ndosu review list --json\ndosu review list --since 7d --json # optional creation-time window\n\n# 2. Inspect — read the exact change before deciding anything.\ndosu review diff <id> --json\n\n# 3. (optional) Edit in place instead of rejecting a near-miss.\ndosu review edit <id> --body-file ./revised.md # or --body / --title (docs only)\n\n# 4. Decide — only on the item the user named, only after they OK it.\ndosu review approve <id> --confirm --json\ndosu review reject <id> --confirm --json\n\n# Undo a doc-change decision — back to pending (not for draft replies).\ndosu review revert <page-version-id> --json\n```\n\n### `--confirm` is mandatory for agents\n\n`approve` and `reject` only prompt interactively in a TTY *without* `--json`.\nThe skill always passes `--json`, which suppresses both the diff preview and\nthe prompt — so without `--confirm` the command changes nothing and returns\n`{ "applied": false, "confirmRequired": true }`. Run `dosu review diff <id>` to\nsee the change, then pass `--confirm` to apply — only after the user has\napproved that specific item.\n\n## Reading the `Source` column\n\n`Source` is the humanized `origin` field:\n\n| `origin` | Source | Meaning |\n|---|---|---|\n| `manual_update` | User created / User updated | A teammate authored or edited the doc |\n| `llm_generated` | AI generated | Dosu drafted the change |\n| `sync_upstream` | Synced from source | Came in from a connected source (Notion/Confluence/GitHub) |\n| `api_update` | Created via API | Pushed in programmatically |\n\n## Feeding PR / thread context\n\nA review often originates from a conversation thread (a GitHub issue, a Slack\nmessage, a sync-back PR). Pull that context before deciding:\n\n```bash\ndosu review context <thread-id> --json\n```\n\nIt returns the review `type`, the review/published page IDs, and — when the\nchange round-trips to an external system — a **Sync PR URL**. Use it to:\n\n- show the user where the change came from and where approval will land, and\n- read the originating discussion so the decision matches intent.\n\n## Safety rules\n\n- **Explicit item only.** Decide on the `id` the user named. "Review my queue"\n → run `list` and show it; never decide on their behalf.\n- **Listing is read-only.** A request to show the list authorizes no approve,\n reject, edit, API-key creation, or deployment switch.\n- **Diff before deciding.** Always `diff` and surface the change first.\n- **Never batch-accept.** No loop over `list` that approves everything. One\n item, one confirmation.\n- **Extra care for sync/PR origins.** `Synced from source` items and anything\n with a Sync PR URL push back to an upstream system on approval. Call it out\n and get explicit sign-off.\n',
61250
+ content: '# Review workflow\n\nHow to work Dosu\'s review queue from the CLI: triage pending items, read the\ndiff, optionally edit, and apply a decision — safely.\n\nThe queue holds **document versions** (AI-generated, user-edited, synced from\nsource, or API-created) and **draft messages**, all surfaced through the same\n`dosu review` commands. Doc changes come from the selected Library; draft\nreplies come only from threads of the selected MCP deployment.\n\n## Read the list result\n\n`dosu review list --json` returns\n`{ "items": [...], "truncated": <bool>, "total": <n>, "scope": {...} }`.\n\n- `items` holds at most 50 entries, newest first, doc changes and draft\n replies merged.\n- `truncated: true` means more pending items may exist than `items` shows.\n- `total` counts what the server found before that cap. When `truncated` is\n true it is a lower bound: report "at least `total`", never an exact backlog.\n- Each `id` is opaque. A doc change\'s `id` is its page-version UUID; a draft\n reply\'s `id` looks like `draft_message:<uuid>` and has `kind: "draft_message"`.\n Pass the `id` exactly as listed to `diff`, `edit`, `approve`, and `reject`;\n do not strip the prefix or shorten it.\n- `--since <when>` and `--until <when>` narrow the list by creation time. Each\n takes a duration back from now (`24h`, `7d`, `2w`), a UTC date\n (`2026-09-01`; an `--until` date includes that whole day), or an ISO-8601\n datetime. When `truncated` is true, `--until` reaches older items.\n\n`scope` says what was searched. It was added alongside the older fields,\nwhich keep their meaning:\n\n- `library`: `{ "id", "name" }` of the Library whose pending doc changes are\n listed.\n- `deployment`: `{ "id", "name" }` of the MCP deployment whose draft replies\n are listed, or `null` when none is saved. Then drafts are not listed.\n- `kinds`: the item kinds searched, `["doc_change", "draft_message"]` or\n `["doc_change"]`.\n- `since` / `until`: the resolved ISO-8601 bounds, or `null` when unbounded.\n\nA `name` is `null` when the server could not provide one; report the ID then\nand do not guess a name. Tell the user which Library the list covers.\n\nAn empty `items` array means no pending items in this scope. It is not a\nreason to switch deployments.\n\n`review list` checks the saved context before listing and fails (exit 1,\nnothing on stdout) instead of returning an empty list when:\n\n- `Not logged in`: run `dosu login`.\n- `No Library selected`: no Library is saved. Follow the context check below.\n- `... is unavailable`: the saved MCP deployment or Library was deleted, or\n the signed-in account cannot access it. Follow the context check below; if\n `dosu deployments list --json` returns nothing, the saved organization may\n be the inaccessible one, and `dosu setup` chooses it again.\n- `... does not match ...`: the saved Library is not the MCP deployment\'s\n Library. The message names the `dosu deployments switch` command that saves\n them together again; run it only after the user confirms.\n\n## Check the context when the scope looks wrong\n\nRun this only when the user says the list is for the wrong Library, names a\ndifferent Library, or a command reports missing context:\n\n1. `dosu status --json`: login state and the selected MCP deployment.\n2. `dosu deployments info --json`: the selected MCP deployment. The list reads\n the Library saved in the CLI\'s config, which `dosu setup` and\n `dosu deployments switch` set to this deployment\'s `space_id`\n (`dosu libraries info <space_id> --json` gives its name). A successful list\n already reports both in `scope`, and a saved Library that does not match\n the deployment\'s is an error.\n3. If that is not the Library the user means, run\n `dosu deployments list --json` and find the MCP deployment whose `space_id`\n matches it (`dosu libraries list --json` maps names to IDs).\n4. Switch only to a deployment the user named or confirmed:\n `dosu deployments switch <deployment-id> --json`. It changes the CLI\'s\n selection for later commands and mints a new API key, so say that it did.\n Never pick the first deployment, and ask when several match or none does.\n5. Run `dosu review list --json` again.\n\n`deployments switch` changes only the CLI\'s saved selection. An AI tool with a\nrunning Dosu MCP connection still points at its previous deployment until\n`dosu mcp refresh` rewrites its MCP entry and the tool restarts or reconnects.\nSay so after a switch; do not run `dosu mcp refresh` unless the user asks.\n\n## Draft reply limits\n\n- `edit` on a draft accepts `--body` or `--body-file` only (no `--title`).\n- `approve` publishes the draft to its thread; `reject` discards it.\n- Drafts have no `revert`. A rejected draft is regenerated on the next agent run.\n\n## Scope tool access for a review session\n\nApproving and rejecting are destructive and outward-facing. When you spin up an\nagent session dedicated to reviewing, scope it to just the review commands:\n\n```yaml\nallowed-tools: Bash(dosu review:*)\n```\n\nThis lets the agent triage, diff, and edit, but keeps it from running unrelated\nCLI commands during a review pass.\n\n## The flow\n\n```bash\n# 1. Triage — what\'s pending? Columns: ID, Kind, Title, Source, Status, Created.\ndosu review list --json\ndosu review list --since 7d --json # optional creation-time window\n\n# 2. Inspect — read the exact change before deciding anything.\ndosu review diff <id> --json\n\n# 3. (optional) Edit in place instead of rejecting a near-miss.\ndosu review edit <id> --body-file ./revised.md # or --body / --title (docs only)\n\n# 4. Decide — only on the item the user named, only after they OK it.\ndosu review approve <id> --confirm --json\ndosu review reject <id> --confirm --json\n\n# Undo a doc-change decision — back to pending (not for draft replies).\ndosu review revert <page-version-id> --json\n```\n\n### `--confirm` is mandatory for agents\n\n`approve` and `reject` only prompt interactively in a TTY *without* `--json`.\nThe skill always passes `--json`, which suppresses both the diff preview and\nthe prompt — so without `--confirm` the command changes nothing and returns\n`{ "applied": false, "confirmRequired": true }`. Run `dosu review diff <id>` to\nsee the change, then pass `--confirm` to apply — only after the user has\napproved that specific item.\n\n## Reading the `Source` column\n\n`Source` is the humanized `origin` field:\n\n| `origin` | Source | Meaning |\n|---|---|---|\n| `manual_update` | User created / User updated | A teammate authored or edited the doc |\n| `llm_generated` | AI generated | Dosu drafted the change |\n| `sync_upstream` | Synced from source | Came in from a connected source (Notion/Confluence/GitHub) |\n| `api_update` | Created via API | Pushed in programmatically |\n\n## Feeding PR / thread context\n\nA review often originates from a conversation thread (a GitHub issue, a Slack\nmessage, a sync-back PR). Pull that context before deciding:\n\n```bash\ndosu review context <thread-id> --json\n```\n\nIt returns the review `type`, the review/published page IDs, and — when the\nchange round-trips to an external system — a **Sync PR URL**. Use it to:\n\n- show the user where the change came from and where approval will land, and\n- read the originating discussion so the decision matches intent.\n\n## Safety rules\n\n- **Explicit item only.** Decide on the `id` the user named. "Review my queue"\n → run `list` and show it; never decide on their behalf.\n- **Listing is read-only.** A request to show the list authorizes no approve,\n reject, edit, API-key creation, or deployment switch.\n- **Diff before deciding.** Always `diff` and surface the change first.\n- **Never batch-accept.** No loop over `list` that approves everything. One\n item, one confirmation.\n- **Extra care for sync/PR origins.** `Synced from source` items and anything\n with a Sync PR URL push back to an upstream system on approval. Call it out\n and get explicit sign-off.\n',
61196
61251
  executable: false
61197
61252
  },
61198
61253
  {
@@ -62328,7 +62383,7 @@ function requireConfig13() {
62328
62383
  }
62329
62384
  return cfg;
62330
62385
  }
62331
- async function getKnowledgeStoreId3(client, spaceId) {
62386
+ async function getKnowledgeStoreId2(client, spaceId) {
62332
62387
  const store = await client.knowledgeStore.getBySpaceId.query({
62333
62388
  space_id: spaceId
62334
62389
  });
@@ -62343,7 +62398,7 @@ function topicsCommand() {
62343
62398
  cmd.command("list").description("List all topics").option("--json", "Output as JSON").action(async (opts) => {
62344
62399
  const cfg = requireConfig13();
62345
62400
  const client = createTypedClient(cfg);
62346
- const ksId = await getKnowledgeStoreId3(client, cfg.active_account.target.space_id);
62401
+ const ksId = await getKnowledgeStoreId2(client, cfg.active_account.target.space_id);
62347
62402
  const topics = await client.topic.listTopicsByKnowledgeStore.query({
62348
62403
  knowledge_store_id: ksId
62349
62404
  });
@@ -62364,7 +62419,7 @@ function topicsCommand() {
62364
62419
  cmd.command("pages").description("List pages with a specific topic").argument("<topic-id>", "Topic ID").option("--search <query>", "Search within the topic's pages").addOption(new Option("--limit <n>", "Maximum results").argParser(positiveInteger).default(10)).option("--json", "Output as JSON").action(async (topicId, opts) => {
62365
62420
  const cfg = requireConfig13();
62366
62421
  const client = createTypedClient(cfg);
62367
- const ksId = await getKnowledgeStoreId3(client, cfg.active_account.target.space_id);
62422
+ const ksId = await getKnowledgeStoreId2(client, cfg.active_account.target.space_id);
62368
62423
  const result = await client.topic.getPagesByTopicId.query({
62369
62424
  knowledge_store_id: ksId,
62370
62425
  topic_id: topicId,
@@ -68912,4 +68967,4 @@ main().catch((err) => {
68912
68967
  process.exit(1);
68913
68968
  });
68914
68969
 
68915
- //# debugId=0891ed1f-f060-16b6-6475-6e2164756e21
68970
+ //# debugId=5d3e9365-4283-2b42-6475-6e2164756e21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dosu/cli",
3
- "version": "0.66.1",
3
+ "version": "0.67.0",
4
4
  "type": "module",
5
5
  "description": "Dosu CLI - Set up Dosu MCP for AI tools and work with Dosu Libraries, docs, and reviews",
6
6
  "license": "MIT",