takomi 2.1.35 → 2.1.37

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 (33) hide show
  1. package/.pi/README.md +6 -3
  2. package/.pi/extensions/oauth-router/commands.ts +36 -35
  3. package/.pi/extensions/oauth-router/index.ts +8 -8
  4. package/.pi/extensions/takomi-context-manager/diagnostics-tools.ts +40 -7
  5. package/.pi/extensions/takomi-context-manager/diagnostics.ts +534 -55
  6. package/.pi/extensions/takomi-context-manager/index.ts +14 -2
  7. package/.pi/extensions/takomi-context-manager/model-policy-gate.ts +16 -4
  8. package/.pi/extensions/takomi-context-manager/policy-tools.ts +7 -0
  9. package/.pi/extensions/takomi-context-manager/prerequisite-gates.ts +2 -0
  10. package/.pi/extensions/takomi-context-manager/session-state.ts +160 -0
  11. package/.pi/extensions/takomi-context-manager/skill-registry.ts +120 -0
  12. package/.pi/extensions/takomi-context-manager/skill-tools.ts +26 -3
  13. package/.pi/extensions/takomi-context-manager/state.ts +11 -1
  14. package/.pi/extensions/takomi-context-manager/types.ts +9 -1
  15. package/.pi/extensions/takomi-runtime/command-text.ts +2 -1
  16. package/.pi/extensions/takomi-runtime/commands.ts +13 -1
  17. package/.pi/extensions/takomi-runtime/index.ts +68 -1
  18. package/.pi/extensions/takomi-runtime/ui.ts +3 -3
  19. package/.pi/extensions/takomi-subagents/index.ts +37 -4
  20. package/.pi/extensions/takomi-subagents/native-render.ts +84 -7
  21. package/.pi/extensions/takomi-subagents/pi-subagents-engine.ts +18 -3
  22. package/.pi/extensions/takomi-subagents/tool-runner.ts +52 -5
  23. package/README.md +14 -7
  24. package/assets/.agent/skills/exam-creator-skill/SKILL.md +182 -0
  25. package/assets/.agent/skills/exam-creator-skill/references/model-routing-policy.md +48 -0
  26. package/assets/.agent/skills/exam-creator-skill/references/workflow-rulebook.md +115 -0
  27. package/package.json +2 -2
  28. package/src/cli.js +134 -13
  29. package/src/doctor.js +7 -1
  30. package/src/harness.js +54 -32
  31. package/src/owned-tree.js +28 -0
  32. package/src/pi-harness.js +149 -24
  33. package/src/store.js +2 -0
package/.pi/README.md CHANGED
@@ -37,7 +37,8 @@ Inside Pi, use:
37
37
  - `/takomi gate auto` to continue approved plans automatically
38
38
  - `/takomi gate review` to return to the user after each task with results and verification guidance
39
39
  - `/takomi subagents on` or `/takomi subagents off` to allow or disable delegated subagents
40
- - `/takomi subagents status|expand|collapse|fullscreen|next|prev|toggle` to inspect or reshape the active subagent stack
40
+ - `/takomi subagents list` to list available Takomi agents without exposing the raw `subagent` tool
41
+ - `/takomi subagents status` to inspect active subagent state
41
42
  - `/takomi-status` to show lifecycle, gate, session, and active subagent state
42
43
  - `/takomi-reset` to reset session-local Takomi runtime state
43
44
  - `/context-report` to inspect prompt compaction, skill loading, policy gates, model routing corrections, and duplicate extension diagnostics
@@ -107,9 +108,9 @@ So when working on packaging, agents should distinguish between:
107
108
  - Task packets can carry `workflow`, `skills`, `preferredModel`, `fallbackModels`, `preferredThinking`, `executionHint`, `conversationId`, and `checklist` metadata.
108
109
  - Direct `takomi_subagent` calls build a `TakomiDelegationPlan` before launch. In auto mode the plan launches immediately; in manual mode the plan is returned for review until `confirmLaunch=true` is supplied.
109
110
  - The subagent tool supports `conversationId`, so reviewed work can be sent back to the same agent for continuation instead of restarting from scratch.
110
- - The subagent tool supports Pi-style single, parallel `tasks`, and sequential `chain` modes.
111
+ - The subagent tool supports Pi-style single, parallel `tasks`, sequential `chain`, explicit `context=fork|fresh`, `async=true`, and native read/control actions such as `action=list`, `action=status`, `action=doctor`, `action=interrupt`, and `action=resume`.
111
112
  - The subagent tool supports `agentScope` values of `user`, `project`, and `both`; project-local agents require confirmation by default.
112
- - The subagent tool also supports per-run `workflow`, `skills`, `model`, `fallbackModels`, `thinking`, and `checklist` overrides.
113
+ - The subagent tool also supports per-run `workflow`, `skills`, `model`, `fallbackModels`, `thinking`, `checklist`, `concurrency`, and `worktree` overrides.
113
114
  - `takomi_board` records session/state/markdown artifacts only; it does not run subagents.
114
115
  - Pi's default `subagent` tool remains owned by the user-level/default subagent extension to avoid tool-name conflicts; Takomi uses `takomi_subagent` as the preferred lifecycle-aware execution interface and renders it with the native Pi-style result surface.
115
116
  - Treat raw `subagent` usage as advanced/internal. Normal Takomi lifecycle execution should go through `takomi_subagent`, then `takomi_board update_task` should record the outcome.
@@ -121,6 +122,8 @@ So when working on packaging, agents should distinguish between:
121
122
  - `takomi-context-manager` gates `takomi_subagent` when model-routing context has not been loaded, provides the routing policy, and tells the agent to retry.
122
123
  - `takomi-context-manager` can correct safe wrong-provider model requests, block or pause on policy violations, and ask the user whether to retry with an approved model or stop.
123
124
  - `takomi-context-manager` detects known duplicate global/project Takomi extension paths in `context_report` to help diagnose tool registration conflicts.
125
+ - `context_report` restores context-manager snapshots and Pi tool-result history after reload/restart and explicitly labels gaps; it is not a replacement for Pi's Alt-C token/session stats.
126
+ - `context_report` defaults to compact `mode: "summary"`; use `mode: "verbose"` for full diagnostics or `mode: "problems"` for attention-only output. `verbose: true` remains a compatibility alias. `/context-report` exposes `summary`, `verbose`, and `problems` as slash-command argument completions.
124
127
  - `takomi_board` can:
125
128
  - create a Genesis-first lifecycle session by default
126
129
  - preserve authored `master_plan.md` and task packet markdown
@@ -273,13 +273,14 @@ export function formatUsageRawReport(runtime: RouterRuntime, accountId?: string)
273
273
  return ["# oauth-router usage raw", "", ...rows].join("\n");
274
274
  }
275
275
 
276
- function emitReport(pi: ExtensionAPI, text: string) {
277
- pi.sendMessage({
278
- customType: "oauth-router",
279
- content: text,
280
- display: true,
281
- details: { source: "oauth-router" },
282
- });
276
+ function emitReport(ctx: ExtensionCommandContext, text: string) {
277
+ const lines = text.split(/\r?\n/);
278
+ const visibleLines = [
279
+ "oauth-router report (UI-only; not sent to the agent)",
280
+ ...lines,
281
+ ];
282
+ ctx.ui.setWidget("oauth-router-report", visibleLines, { placement: "belowEditor" });
283
+ ctx.ui.notify(lines[0] || "oauth-router report updated", "info");
283
284
  }
284
285
 
285
286
  async function pickUpstream(runtime: RouterRuntime, ctx: ExtensionCommandContext, requestedId?: string) {
@@ -388,12 +389,12 @@ function setFooterStatus(ctx: ExtensionCommandContext, runtime: RouterRuntime) {
388
389
  ctx.ui.setStatus("oauth-router", `oauth-router ${healthy}/${rows.length || 0} healthy | ${runtime.getPolicy()}`);
389
390
  }
390
391
 
391
- function showCommandHint(pi: ExtensionAPI, ctx: ExtensionCommandContext, title: string, lines: string[]) {
392
- emitReport(pi, [`# ${title}`, "", ...lines].join("\n"));
392
+ function showCommandHint(ctx: ExtensionCommandContext, title: string, lines: string[]) {
393
+ emitReport(ctx, [`# ${title}`, "", ...lines].join("\n"));
393
394
  ctx.ui.notify(title, "info");
394
395
  }
395
396
 
396
- async function handleRouterLogin(pi: ExtensionAPI, runtime: RouterRuntime, args: string, ctx: ExtensionCommandContext) {
397
+ async function handleRouterLogin(runtime: RouterRuntime, args: string, ctx: ExtensionCommandContext) {
397
398
  const [command = "help", first, ...rest] = parseArgs(args);
398
399
 
399
400
  switch (command) {
@@ -418,18 +419,18 @@ async function handleRouterLogin(pi: ExtensionAPI, runtime: RouterRuntime, args:
418
419
  runtime.clearAccountHealth(duplicate.id);
419
420
  const usageMessage = await refreshUsageAfterCredentialChange(runtime, duplicate.id);
420
421
  setFooterStatus(ctx, runtime);
421
- emitReport(pi, `Updated existing account ${duplicate.id} (${duplicate.label}) with fresh credentials instead of adding a duplicate.${usageMessage}`);
422
+ emitReport(ctx, `Updated existing account ${duplicate.id} (${duplicate.label}) with fresh credentials instead of adding a duplicate.${usageMessage}`);
422
423
  return;
423
424
  }
424
425
  runtime.addAccount(account);
425
426
  const usageMessage = await refreshUsageAfterCredentialChange(runtime, account.id);
426
427
  setFooterStatus(ctx, runtime);
427
- emitReport(pi, `Added account ${account.id} (${account.label}) for upstream ${upstream.id}.${usageMessage}`);
428
+ emitReport(ctx, `Added account ${account.id} (${account.label}) for upstream ${upstream.id}.${usageMessage}`);
428
429
  ctx.ui.notify(`Added ${account.id}`, "info");
429
430
  return;
430
431
  }
431
432
  case "list": {
432
- emitReport(pi, formatAccountsReport(runtime));
433
+ emitReport(ctx, formatAccountsReport(runtime));
433
434
  setFooterStatus(ctx, runtime);
434
435
  return;
435
436
  }
@@ -442,7 +443,7 @@ async function handleRouterLogin(pi: ExtensionAPI, runtime: RouterRuntime, args:
442
443
  }
443
444
  runtime.removeAccount(account.id);
444
445
  setFooterStatus(ctx, runtime);
445
- emitReport(pi, `Removed account ${account.id}.`);
446
+ emitReport(ctx, `Removed account ${account.id}.`);
446
447
  return;
447
448
  }
448
449
  case "rename": {
@@ -450,7 +451,7 @@ async function handleRouterLogin(pi: ExtensionAPI, runtime: RouterRuntime, args:
450
451
  const label = await getRequiredLabel(ctx, account.label, rest.join(" "));
451
452
  runtime.renameAccount(account.id, label);
452
453
  setFooterStatus(ctx, runtime);
453
- emitReport(pi, `Renamed account ${account.id} to ${label}.`);
454
+ emitReport(ctx, `Renamed account ${account.id} to ${label}.`);
454
455
  return;
455
456
  }
456
457
  case "relogin": {
@@ -475,7 +476,7 @@ async function handleRouterLogin(pi: ExtensionAPI, runtime: RouterRuntime, args:
475
476
  runtime.clearAccountHealth(existing.id);
476
477
  const usageMessage = await refreshUsageAfterCredentialChange(runtime, existing.id);
477
478
  setFooterStatus(ctx, runtime);
478
- emitReport(pi, `Re-logged account ${existing.id} (${existing.label}) and cleared auth state.${usageMessage}`);
479
+ emitReport(ctx, `Re-logged account ${existing.id} (${existing.label}) and cleared auth state.${usageMessage}`);
479
480
  return;
480
481
  }
481
482
  case "refresh": {
@@ -483,13 +484,13 @@ async function handleRouterLogin(pi: ExtensionAPI, runtime: RouterRuntime, args:
483
484
  const refreshed = await runtime.refreshAccount(account.id);
484
485
  const usageMessage = await refreshUsageAfterCredentialChange(runtime, refreshed.id);
485
486
  setFooterStatus(ctx, runtime);
486
- emitReport(pi, `Refreshed account ${refreshed.id} (${refreshed.label}).${usageMessage}`);
487
+ emitReport(ctx, `Refreshed account ${refreshed.id} (${refreshed.label}).${usageMessage}`);
487
488
  return;
488
489
  }
489
490
  case "help":
490
491
  default: {
491
492
  emitReport(
492
- pi,
493
+ ctx,
493
494
  [
494
495
  "# oauth-router commands",
495
496
  "",
@@ -519,13 +520,13 @@ async function handleRouterLogin(pi: ExtensionAPI, runtime: RouterRuntime, args:
519
520
  export function registerRouterCommands(pi: ExtensionAPI, runtime: RouterRuntime) {
520
521
  pi.registerCommand("router-login", {
521
522
  description: "Manage oauth-router accounts",
522
- handler: async (args, ctx) => handleRouterLogin(pi, runtime, args || "", ctx),
523
+ handler: async (args, ctx) => handleRouterLogin(runtime, args || "", ctx),
523
524
  });
524
525
 
525
526
  pi.registerCommand("router-status", {
526
527
  description: "Show oauth-router health and routing state",
527
528
  handler: async (_args, ctx) => {
528
- emitReport(pi, formatStatusReport(runtime));
529
+ emitReport(ctx, formatStatusReport(runtime));
529
530
  setFooterStatus(ctx, runtime);
530
531
  },
531
532
  });
@@ -533,7 +534,7 @@ export function registerRouterCommands(pi: ExtensionAPI, runtime: RouterRuntime)
533
534
  pi.registerCommand("router-accounts", {
534
535
  description: "Show compact oauth-router account list",
535
536
  handler: async (_args, ctx) => {
536
- emitReport(pi, formatAccountsReport(runtime));
537
+ emitReport(ctx, formatAccountsReport(runtime));
537
538
  setFooterStatus(ctx, runtime);
538
539
  },
539
540
  });
@@ -542,7 +543,7 @@ export function registerRouterCommands(pi: ExtensionAPI, runtime: RouterRuntime)
542
543
  description: "Show oauth-router visual provider quota and local usage",
543
544
  handler: async (args, ctx) => {
544
545
  const [id] = parseArgs(args || "");
545
- emitReport(pi, formatUsageReport(runtime, id));
546
+ emitReport(ctx, formatUsageReport(runtime, id));
546
547
  setFooterStatus(ctx, runtime);
547
548
  },
548
549
  });
@@ -551,7 +552,7 @@ export function registerRouterCommands(pi: ExtensionAPI, runtime: RouterRuntime)
551
552
  description: "Show raw oauth-router usage/provider quota details",
552
553
  handler: async (args, ctx) => {
553
554
  const [id] = parseArgs(args || "");
554
- emitReport(pi, formatUsageRawReport(runtime, id));
555
+ emitReport(ctx, formatUsageRawReport(runtime, id));
555
556
  setFooterStatus(ctx, runtime);
556
557
  },
557
558
  });
@@ -560,7 +561,7 @@ export function registerRouterCommands(pi: ExtensionAPI, runtime: RouterRuntime)
560
561
  description: "Alias for visual oauth-router usage/quota",
561
562
  handler: async (args, ctx) => {
562
563
  const [id] = parseArgs(args || "");
563
- emitReport(pi, formatUsageReport(runtime, id));
564
+ emitReport(ctx, formatUsageReport(runtime, id));
564
565
  setFooterStatus(ctx, runtime);
565
566
  },
566
567
  });
@@ -583,7 +584,7 @@ export function registerRouterCommands(pi: ExtensionAPI, runtime: RouterRuntime)
583
584
  }
584
585
 
585
586
  const report = formatUsageReport(runtime, target === "all" ? undefined : target);
586
- emitReport(pi, failures.length ? [report, "", "## Refresh failures", ...failures].join("\n") : report);
587
+ emitReport(ctx, failures.length ? [report, "", "## Refresh failures", ...failures].join("\n") : report);
587
588
  if (failures.length) ctx.ui.notify(`oauth-router usage refreshed with ${failures.length} failure(s)`, "error");
588
589
  setFooterStatus(ctx, runtime);
589
590
  },
@@ -597,7 +598,7 @@ export function registerRouterCommands(pi: ExtensionAPI, runtime: RouterRuntime)
597
598
  const label = await getRequiredLabel(ctx, account.label, labelParts.join(" "));
598
599
  runtime.renameAccount(account.id, label);
599
600
  setFooterStatus(ctx, runtime);
600
- emitReport(pi, `Renamed account ${account.id} to ${label}.`);
601
+ emitReport(ctx, `Renamed account ${account.id} to ${label}.`);
601
602
  },
602
603
  });
603
604
 
@@ -612,13 +613,13 @@ export function registerRouterCommands(pi: ExtensionAPI, runtime: RouterRuntime)
612
613
  }
613
614
  runtime.removeAccount(account.id);
614
615
  setFooterStatus(ctx, runtime);
615
- emitReport(pi, `Deleted account ${account.id}.`);
616
+ emitReport(ctx, `Deleted account ${account.id}.`);
616
617
  },
617
618
  });
618
619
 
619
620
  pi.registerCommand("router-relogin", {
620
621
  description: "Re-login and recover an oauth-router account",
621
- handler: async (args, ctx) => handleRouterLogin(pi, runtime, `relogin ${args || ""}`, ctx),
622
+ handler: async (args, ctx) => handleRouterLogin(runtime, `relogin ${args || ""}`, ctx),
622
623
  });
623
624
 
624
625
  pi.registerCommand("router-enable", {
@@ -628,7 +629,7 @@ export function registerRouterCommands(pi: ExtensionAPI, runtime: RouterRuntime)
628
629
  const account = await pickAccount(runtime, ctx, id, "Choose account to enable");
629
630
  runtime.setEnabled(account.id, true);
630
631
  setFooterStatus(ctx, runtime);
631
- emitReport(pi, `Enabled account ${account.id}.`);
632
+ emitReport(ctx, `Enabled account ${account.id}.`);
632
633
  },
633
634
  });
634
635
 
@@ -639,7 +640,7 @@ export function registerRouterCommands(pi: ExtensionAPI, runtime: RouterRuntime)
639
640
  const account = await pickAccount(runtime, ctx, id, "Choose account to disable");
640
641
  runtime.setEnabled(account.id, false);
641
642
  setFooterStatus(ctx, runtime);
642
- emitReport(pi, `Disabled account ${account.id}.`);
643
+ emitReport(ctx, `Disabled account ${account.id}.`);
643
644
  },
644
645
  });
645
646
 
@@ -649,7 +650,7 @@ export function registerRouterCommands(pi: ExtensionAPI, runtime: RouterRuntime)
649
650
  const raw = (args || "").trim();
650
651
  const policy = normalizePolicy(raw);
651
652
  if (!raw) {
652
- showCommandHint(pi, ctx, "router-policy", [
653
+ showCommandHint(ctx, "router-policy", [
653
654
  `Current policy: ${runtime.getPolicy()}`,
654
655
  "",
655
656
  "Usage: /router-policy <round-robin|weighted-round-robin>",
@@ -658,7 +659,7 @@ export function registerRouterCommands(pi: ExtensionAPI, runtime: RouterRuntime)
658
659
  return;
659
660
  }
660
661
  if (!policy) {
661
- showCommandHint(pi, ctx, "router-policy", [
662
+ showCommandHint(ctx, "router-policy", [
662
663
  `Unrecognized policy: ${raw}`,
663
664
  "",
664
665
  `Current policy: ${runtime.getPolicy()}`,
@@ -668,7 +669,7 @@ export function registerRouterCommands(pi: ExtensionAPI, runtime: RouterRuntime)
668
669
  }
669
670
  runtime.setPolicy(policy);
670
671
  setFooterStatus(ctx, runtime);
671
- emitReport(pi, `Routing policy set to ${policy}.`);
672
+ emitReport(ctx, `Routing policy set to ${policy}.`);
672
673
  },
673
674
  });
674
675
 
@@ -683,12 +684,12 @@ export function registerRouterCommands(pi: ExtensionAPI, runtime: RouterRuntime)
683
684
  weight = Number(response);
684
685
  }
685
686
  if (!Number.isFinite(weight)) {
686
- showCommandHint(pi, ctx, "router-weight", ["Usage: /router-weight <id> <n>", "Example: /router-weight acct_ab12cd34 3"]);
687
+ showCommandHint(ctx, "router-weight", ["Usage: /router-weight <id> <n>", "Example: /router-weight acct_ab12cd34 3"]);
687
688
  return;
688
689
  }
689
690
  runtime.setWeight(account.id, weight);
690
691
  setFooterStatus(ctx, runtime);
691
- emitReport(pi, `Updated weight for ${account.id} to ${Math.max(1, Math.floor(weight))}.`);
692
+ emitReport(ctx, `Updated weight for ${account.id} to ${Math.max(1, Math.floor(weight))}.`);
692
693
  },
693
694
  });
694
695
  }
@@ -117,14 +117,14 @@ export default function (pi: ExtensionAPI) {
117
117
  installRouterUiBridge(pi, runtime, false);
118
118
 
119
119
  pi.registerCommand("router-debug-report", {
120
- description: "Emit a detailed oauth-router report",
121
- handler: async () => {
122
- pi.sendMessage({
123
- customType: "oauth-router",
124
- content: formatStatusReport(runtime),
125
- display: true,
126
- details: { source: "oauth-router", debug: true },
127
- });
120
+ description: "Show a detailed oauth-router report in the UI only",
121
+ handler: async (_args, ctx) => {
122
+ const report = formatStatusReport(runtime);
123
+ ctx.ui.setWidget("oauth-router-report", [
124
+ "oauth-router debug report (UI-only; not sent to the agent)",
125
+ ...report.split(/\r?\n/),
126
+ ], { placement: "belowEditor" });
127
+ ctx.ui.notify("oauth-router debug report updated", "info");
128
128
  },
129
129
  });
130
130
  }
@@ -1,28 +1,61 @@
1
1
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+ import type { AutocompleteItem } from "@earendil-works/pi-tui";
2
3
  import { Type } from "typebox";
3
4
  import type { ContextManagerState } from "./state";
4
- import { renderReport } from "./diagnostics";
5
+ import { renderReport, type ContextReportMode } from "./diagnostics";
6
+ import { discoverSkillsFromFilesystem, mergeSkills } from "./skill-registry";
7
+ import { persistReportSnapshot, restoreReportFromSession } from "./session-state";
5
8
 
6
9
  export function registerDiagnostics(pi: ExtensionAPI, state: ContextManagerState): void {
7
10
  pi.registerTool({
8
11
  name: "context_report",
9
12
  label: "Context Report",
10
- description: "Show takomi-context-manager diagnostics for prompt rewriting, candidates, policies, gates, and progressive skill loading.",
13
+ description: "Show takomi-context-manager diagnostics. Defaults to compact summary; use mode='verbose' for full details or mode='problems' for attention-only output.",
11
14
  promptSnippet: "Show context manager diagnostics and prompt composition decisions",
12
- parameters: Type.Object({ verbose: Type.Optional(Type.Boolean({ description: "Include skill and policy indexes in the report" })) }),
15
+ parameters: Type.Object({
16
+ mode: Type.Optional(Type.Union([
17
+ Type.Literal("summary"),
18
+ Type.Literal("verbose"),
19
+ Type.Literal("problems"),
20
+ ], { description: "Report layout mode. Defaults to summary. Use verbose for full diagnostics or problems for attention-only output." })),
21
+ verbose: Type.Optional(Type.Boolean({ description: "Deprecated compatibility alias for mode='verbose'." })),
22
+ }),
13
23
  async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
24
+ restoreReportFromSession(state, ctx);
25
+ if (state.skills.size === 0) state.skills = mergeSkills(await discoverSkillsFromFilesystem(ctx.cwd));
26
+ state.report.timestamp = new Date().toISOString();
14
27
  state.report.cwd = ctx.cwd;
28
+ state.report.skillCount = state.skills.size;
15
29
  state.report.toolCalls.contextReport += 1;
16
- return { content: [{ type: "text", text: renderReport(state, params.verbose ?? false) }], details: state.report };
30
+ persistReportSnapshot(pi, state, "context_report");
31
+ const mode = (params.verbose ? "verbose" : params.mode ?? "summary") as ContextReportMode;
32
+ return { content: [{ type: "text", text: renderReport(state, mode) }], details: { ...state.report, mode } };
17
33
  },
18
34
  });
19
35
 
20
36
  pi.registerCommand("context-report", {
21
- description: "Show takomi-context-manager diagnostics",
22
- handler: async (_args, ctx) => {
37
+ description: "Show takomi-context-manager diagnostics. Optional args: summary, verbose, problems",
38
+ getArgumentCompletions: (prefix: string): AutocompleteItem[] | null => {
39
+ const modes: AutocompleteItem[] = [
40
+ { value: "summary", label: "summary — compact health report" },
41
+ { value: "verbose", label: "verbose — full diagnostics" },
42
+ { value: "problems", label: "problems — only issues requiring attention" },
43
+ ];
44
+ const normalized = prefix.trim().toLowerCase();
45
+ const filtered = modes.filter((mode) => mode.value.startsWith(normalized));
46
+ return filtered.length ? filtered : null;
47
+ },
48
+ handler: async (args, ctx) => {
49
+ restoreReportFromSession(state, ctx);
50
+ if (state.skills.size === 0) state.skills = mergeSkills(await discoverSkillsFromFilesystem(ctx.cwd));
51
+ state.report.timestamp = new Date().toISOString();
23
52
  state.report.cwd = ctx.cwd;
53
+ state.report.skillCount = state.skills.size;
24
54
  state.report.toolCalls.contextReport += 1;
25
- ctx.ui.notify(renderReport(state, true), "info");
55
+ persistReportSnapshot(pi, state, "context-report-command");
56
+ const requested = args.trim();
57
+ const mode: ContextReportMode = requested === "verbose" || requested === "problems" || requested === "summary" ? requested : "summary";
58
+ ctx.ui.notify(renderReport(state, mode), "info");
26
59
  },
27
60
  });
28
61
  }