@questionbase/deskfree 0.3.0-alpha.20 → 0.3.0-alpha.21

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.
package/README.md CHANGED
@@ -15,7 +15,7 @@ Agents can pick up tasks, post progress updates, mark work as done or blocked, m
15
15
  │ deskfree_state Inbound messages from humans │
16
16
  │ deskfree_start_task Outbound replies from agent │
17
17
  │ deskfree_complete_task Real-time notifications │
18
- deskfree_create_task
18
+ deskfree_suggest_tasks
19
19
  │ deskfree_create_activity │
20
20
  │ deskfree_update_activity │
21
21
  │ deskfree_classify_task │
package/dist/index.d.ts CHANGED
@@ -442,13 +442,6 @@ interface TaskWithContext extends Task {
442
442
  deliverable: string;
443
443
  messages: TaskMessage[];
444
444
  }
445
- /**
446
- * Response from the tasks.create bot endpoint.
447
- *
448
- * The backend mutation (`trpc.bot.tasks.create`) returns the Task object
449
- * directly (not wrapped in `{ task: ... }`).
450
- */
451
- type CreateTaskResponse = Task;
452
445
  interface CompleteTaskInput {
453
446
  taskId: string;
454
447
  outcome: 'done' | 'blocked';
@@ -463,6 +456,15 @@ interface WorkspaceStateTask {
463
456
  createdAt: string;
464
457
  updatedAt: string;
465
458
  }
459
+ interface Initiative {
460
+ id: string;
461
+ title: string;
462
+ status: 'suggested' | 'active' | 'paused';
463
+ content: string;
464
+ contentVersion: number;
465
+ taskCount: number;
466
+ activeTaskCount: number;
467
+ }
466
468
  interface WorkspaceState {
467
469
  tasks: WorkspaceStateTask[];
468
470
  recentlyDone: WorkspaceStateTask[];
@@ -471,7 +473,9 @@ interface WorkspaceState {
471
473
  taskId: string;
472
474
  taskNumber: number;
473
475
  title: string;
476
+ initiativeId?: string | null;
474
477
  }>;
478
+ initiatives: Initiative[];
475
479
  }
476
480
  interface EvaluationTaskMessage {
477
481
  messageId: string;
@@ -487,6 +491,11 @@ interface ClaimEvaluationResponse {
487
491
  waysOfWorking: string | null;
488
492
  currentVersion: number;
489
493
  messages: EvaluationTaskMessage[];
494
+ initiative?: {
495
+ id: string;
496
+ title: string;
497
+ content: string;
498
+ } | null;
490
499
  }
491
500
 
492
501
  /** Enhanced error class for DeskFree API errors with user-friendly messages */
@@ -558,19 +567,6 @@ declare class DeskFreeClient {
558
567
  }): Promise<MessagesResponse>;
559
568
  /** Obtain a one-time WebSocket authentication ticket for real-time notifications. */
560
569
  getWsTicket(): Promise<WsTicketResponse>;
561
- /** Create a new task, optionally with a recurring schedule. */
562
- createTask(input: {
563
- title: string;
564
- instructions?: string;
565
- isRecurring?: boolean;
566
- recurringSchedule?: {
567
- frequency: 'daily' | 'weekly' | 'biweekly' | 'monthly';
568
- dayOfWeek?: number;
569
- dayOfMonth?: number;
570
- time: string;
571
- timezone?: string;
572
- };
573
- }): Promise<CreateTaskResponse>;
574
570
  /** Claim a task so the bot can begin working on it. Returns enriched context. */
575
571
  claimTask(input: {
576
572
  taskId: string;
@@ -638,6 +634,25 @@ declare class DeskFreeClient {
638
634
  messageId: string;
639
635
  content: string;
640
636
  }>;
637
+ /** Suggest tasks via the dedicated bot/tasks.suggest endpoint. */
638
+ suggestTasksDedicated(input: {
639
+ suggestions: Array<{
640
+ title: string;
641
+ instructions?: string;
642
+ estimatedTokens?: number;
643
+ dependsOn?: string[];
644
+ initiativeId?: string;
645
+ }>;
646
+ parentTaskId?: string;
647
+ initiativeSuggestions?: Array<{
648
+ title: string;
649
+ content: string;
650
+ taskRefs?: number[];
651
+ }>;
652
+ }): Promise<{
653
+ suggestionIds: string[];
654
+ initiativeSuggestionIds?: string[];
655
+ }>;
641
656
  /**
642
657
  * Claim a pending evaluation for a task. Atomically sets isWorking=true where
643
658
  * evaluationPending=true and isWorking=false. Returns null if already claimed.
@@ -647,17 +662,24 @@ declare class DeskFreeClient {
647
662
  }): Promise<ClaimEvaluationResponse | null>;
648
663
  /**
649
664
  * Submit the result of a ways-of-working evaluation.
650
- * If hasChanges is true and updatedContent is provided, inserts a new version.
665
+ * Dual output: globalWoW (applies everywhere) and initiative (applies to the task's initiative).
651
666
  * Clears evaluationPending and isWorking on the task.
652
667
  */
653
668
  submitEvaluation(input: {
654
669
  taskId: string;
655
- updatedContent?: string;
656
670
  reasoning: string;
657
- hasChanges: boolean;
671
+ globalWoW: {
672
+ hasChanges: boolean;
673
+ updatedContent?: string;
674
+ };
675
+ initiative: {
676
+ hasChanges: boolean;
677
+ updatedContent?: string;
678
+ };
658
679
  }): Promise<{
659
680
  success: boolean;
660
- version?: number;
681
+ globalVersion?: number;
682
+ initiativeVersion?: number;
661
683
  }>;
662
684
  /**
663
685
  * Lightweight health check that verifies connectivity and authentication.
@@ -725,4 +747,4 @@ declare const plugin: {
725
747
  register(api: OpenClawPluginApi): void;
726
748
  };
727
749
 
728
- export { type AnyAgentTool, type ChannelAccountSnapshot, type ChannelCapabilities, type ChannelConfigAdapter, type ChannelGatewayAdapter, type ChannelGatewayContext, type ChannelLogoutContext, type ChannelLogoutResult, type ChannelMessagingAdapter, type ChannelMessagingTargetResolver, type ChannelMeta, type ChannelOnboardingAdapter, type ChannelOnboardingResult, type ChannelOnboardingStatus, type ChannelOutboundAdapter, type ChannelOutboundContext, type ChannelPlugin, type ChannelProbeResult, type ChannelSecurityAdapter, type ChannelSecurityDmPolicy, type ChannelSetupAdapter, type ChannelStatusAdapter, type ChannelStatusIssue, type ChatMessage, type ChatMessageAttachment, type ClaimEvaluationResponse, type CompleteTaskInput, type CreateTaskResponse, type DeskFreeChannelConfig, DeskFreeClient, DeskFreeError, type EvaluationTaskMessage, type FinalizedMsgContext, type MessagesResponse, OfflineQueue, type OpenClawConfig, type OpenClawPluginApi, type OpenClawPluginToolContext, type OpenClawPluginToolFactory, type OpenClawPluginToolOptions, type OutboundDeliveryResult, type PluginHookAgentContext, type PluginHookBeforeAgentStartEvent, type PluginHookBeforeAgentStartResult, type PluginHookHandlerMap, type PluginHookName, type PluginLogger, type PluginRuntime, type ReplyDispatcher, type ResolvedDeskFreeAccount, type Task, type TaskMessage, type TaskWithContext, type WizardPrompter, type WorkspaceState, type WorkspaceStateTask, type WsNotification, type WsTicketResponse, plugin as default, reportError };
750
+ export { type AnyAgentTool, type ChannelAccountSnapshot, type ChannelCapabilities, type ChannelConfigAdapter, type ChannelGatewayAdapter, type ChannelGatewayContext, type ChannelLogoutContext, type ChannelLogoutResult, type ChannelMessagingAdapter, type ChannelMessagingTargetResolver, type ChannelMeta, type ChannelOnboardingAdapter, type ChannelOnboardingResult, type ChannelOnboardingStatus, type ChannelOutboundAdapter, type ChannelOutboundContext, type ChannelPlugin, type ChannelProbeResult, type ChannelSecurityAdapter, type ChannelSecurityDmPolicy, type ChannelSetupAdapter, type ChannelStatusAdapter, type ChannelStatusIssue, type ChatMessage, type ChatMessageAttachment, type ClaimEvaluationResponse, type CompleteTaskInput, type DeskFreeChannelConfig, DeskFreeClient, DeskFreeError, type EvaluationTaskMessage, type FinalizedMsgContext, type Initiative, type MessagesResponse, OfflineQueue, type OpenClawConfig, type OpenClawPluginApi, type OpenClawPluginToolContext, type OpenClawPluginToolFactory, type OpenClawPluginToolOptions, type OutboundDeliveryResult, type PluginHookAgentContext, type PluginHookBeforeAgentStartEvent, type PluginHookBeforeAgentStartResult, type PluginHookHandlerMap, type PluginHookName, type PluginLogger, type PluginRuntime, type ReplyDispatcher, type ResolvedDeskFreeAccount, type Task, type TaskMessage, type TaskWithContext, type WizardPrompter, type WorkspaceState, type WorkspaceStateTask, type WsNotification, type WsTicketResponse, plugin as default, reportError };
package/dist/index.js CHANGED
@@ -3889,11 +3889,6 @@ var DeskFreeClient = class {
3889
3889
  return this.request("POST", "messages.wsTicket", {});
3890
3890
  }
3891
3891
  // ── Tasks ─────────────────────────────────────────────────
3892
- /** Create a new task, optionally with a recurring schedule. */
3893
- async createTask(input) {
3894
- this.requireNonEmpty(input.title, "title");
3895
- return this.request("POST", "tasks.create", input);
3896
- }
3897
3892
  /** Claim a task so the bot can begin working on it. Returns enriched context. */
3898
3893
  async claimTask(input) {
3899
3894
  this.requireNonEmpty(input.taskId, "taskId");
@@ -3943,6 +3938,18 @@ var DeskFreeClient = class {
3943
3938
  taskId: input.taskId
3944
3939
  });
3945
3940
  }
3941
+ /** Suggest tasks via the dedicated bot/tasks.suggest endpoint. */
3942
+ async suggestTasksDedicated(input) {
3943
+ if (!input.suggestions || input.suggestions.length === 0) {
3944
+ throw new DeskFreeError(
3945
+ "client",
3946
+ "suggestions",
3947
+ "suggestions array is required and cannot be empty",
3948
+ "Missing required parameter: suggestions."
3949
+ );
3950
+ }
3951
+ return this.request("POST", "tasks.suggest", input);
3952
+ }
3946
3953
  /**
3947
3954
  * Claim a pending evaluation for a task. Atomically sets isWorking=true where
3948
3955
  * evaluationPending=true and isWorking=false. Returns null if already claimed.
@@ -3953,7 +3960,7 @@ var DeskFreeClient = class {
3953
3960
  }
3954
3961
  /**
3955
3962
  * Submit the result of a ways-of-working evaluation.
3956
- * If hasChanges is true and updatedContent is provided, inserts a new version.
3963
+ * Dual output: globalWoW (applies everywhere) and initiative (applies to the task's initiative).
3957
3964
  * Clears evaluationPending and isWorking on the task.
3958
3965
  */
3959
3966
  async submitEvaluation(input) {
@@ -7755,19 +7762,9 @@ var Type = type_exports2;
7755
7762
  var ORCHESTRATOR_TOOLS = {
7756
7763
  STATE: {
7757
7764
  name: "deskfree_state",
7758
- description: "Get full workspace state \u2014 all tasks, recently done tasks. Use to assess what needs attention.",
7765
+ description: "Get full workspace state \u2014 all tasks, recently done tasks, active initiatives. Use to assess what needs attention.",
7759
7766
  parameters: Type.Object({})
7760
7767
  },
7761
- CREATE_TASK: {
7762
- name: "deskfree_create_task",
7763
- description: "Create a new task (starts as bot).",
7764
- parameters: Type.Object({
7765
- title: Type.String({ description: "Task title (max 200 chars)" }),
7766
- instructions: Type.Optional(
7767
- Type.String({ description: "Detailed instructions for the task" })
7768
- )
7769
- })
7770
- },
7771
7768
  START_TASK: {
7772
7769
  name: "deskfree_start_task",
7773
7770
  description: "Claim a bot task (isWorking=false) and start working. Returns full context (instructions, deliverable, message history).",
@@ -7833,28 +7830,115 @@ var ORCHESTRATOR_TOOLS = {
7833
7830
  )
7834
7831
  })
7835
7832
  },
7833
+ SUGGEST_TASKS: {
7834
+ name: "deskfree_suggest_tasks",
7835
+ description: 'Suggest tasks for human approval. Tasks are created with "suggested" status \u2014 the human approves or rejects each one. Use this to propose work before starting. Include detailed instructions as if briefing a contractor.',
7836
+ parameters: Type.Object({
7837
+ suggestions: Type.Array(
7838
+ Type.Object({
7839
+ title: Type.String({
7840
+ description: "Task title \u2014 short, action-oriented (max 200 chars)"
7841
+ }),
7842
+ instructions: Type.Optional(
7843
+ Type.String({
7844
+ description: "Detailed instructions: what to do, why, what done looks like, known constraints"
7845
+ })
7846
+ ),
7847
+ estimatedTokens: Type.Optional(
7848
+ Type.Number({
7849
+ description: "Estimated token cost \u2014 consider files to read, reasoning, output"
7850
+ })
7851
+ ),
7852
+ dependsOn: Type.Optional(
7853
+ Type.Array(Type.String(), {
7854
+ description: "Task IDs this suggestion depends on (blocks claiming until those are done)"
7855
+ })
7856
+ ),
7857
+ initiativeId: Type.Optional(
7858
+ Type.String({
7859
+ description: "Link to existing initiative ID \u2014 set when this task belongs to an active initiative"
7860
+ })
7861
+ )
7862
+ }),
7863
+ {
7864
+ description: "Array of task suggestions (1-20)",
7865
+ minItems: 1,
7866
+ maxItems: 20
7867
+ }
7868
+ ),
7869
+ parentTaskId: Type.Optional(
7870
+ Type.String({
7871
+ description: "Parent task ID \u2014 set when suggesting follow-ups from within a task"
7872
+ })
7873
+ ),
7874
+ initiativeSuggestions: Type.Optional(
7875
+ Type.Array(
7876
+ Type.Object({
7877
+ title: Type.String({
7878
+ description: "Initiative title (max 200 chars)"
7879
+ }),
7880
+ content: Type.String({
7881
+ description: "Initiative content markdown \u2014 current state, approach, and next priorities"
7882
+ }),
7883
+ taskRefs: Type.Optional(
7884
+ Type.Array(Type.Number(), {
7885
+ description: "Indexes into suggestions[] to auto-link when this initiative is approved"
7886
+ })
7887
+ )
7888
+ }),
7889
+ {
7890
+ description: 'Propose new initiatives (optional). Created with "suggested" status \u2014 human approves or rejects independently.',
7891
+ minItems: 1,
7892
+ maxItems: 10
7893
+ }
7894
+ )
7895
+ )
7896
+ })
7897
+ },
7836
7898
  CLAIM_EVALUATION: {
7837
7899
  name: "deskfree_claim_evaluation",
7838
- description: "Claim a pending ways-of-working evaluation for a task. Returns the task, its message history, and current ways_of_working content so you can decide whether updates are needed. Returns null if already claimed by another process.",
7900
+ description: "Claim a pending ways-of-working evaluation for a task. Returns the task, its message history, current global ways_of_working, and initiative data (if the task belongs to an initiative). Returns null if already claimed by another process.",
7839
7901
  parameters: Type.Object({
7840
7902
  taskId: Type.String({ description: "Task UUID to claim evaluation for" })
7841
7903
  })
7842
7904
  },
7843
7905
  SUBMIT_EVALUATION: {
7844
7906
  name: "deskfree_submit_evaluation",
7845
- description: "Submit the result of a ways-of-working evaluation. Provide reasoning explaining your analysis. If the task revealed new patterns or learnings worth capturing, set hasChanges=true and provide updatedContent with the full updated markdown. Otherwise set hasChanges=false.",
7907
+ description: "Submit the result of a ways-of-working evaluation. Provide reasoning explaining your analysis. Evaluation has two independent outputs: globalWoW (applies everywhere) and initiative (applies to the specific initiative this task belongs to). Set hasChanges=true and provide updatedContent for each output you want to update.",
7846
7908
  parameters: Type.Object({
7847
7909
  taskId: Type.String({ description: "Task UUID being evaluated" }),
7848
7910
  reasoning: Type.String({
7849
- description: "Explanation of your evaluation \u2014 what you analyzed and why you did or did not update the ways of working"
7850
- }),
7851
- hasChanges: Type.Boolean({
7852
- description: "Whether the ways of working should be updated"
7911
+ description: "Explanation of your evaluation \u2014 what you analyzed and why you did or did not update the ways of working and/or initiative content"
7853
7912
  }),
7854
- updatedContent: Type.Optional(
7855
- Type.String({
7856
- description: "Full updated ways-of-working markdown (required if hasChanges=true)"
7857
- })
7913
+ globalWoW: Type.Object(
7914
+ {
7915
+ hasChanges: Type.Boolean({
7916
+ description: "Whether the global ways of working should be updated"
7917
+ }),
7918
+ updatedContent: Type.Optional(
7919
+ Type.String({
7920
+ description: "Full updated global ways-of-working markdown (required if hasChanges=true)"
7921
+ })
7922
+ )
7923
+ },
7924
+ {
7925
+ description: "Global ways-of-working update \u2014 patterns that apply across all work"
7926
+ }
7927
+ ),
7928
+ initiative: Type.Object(
7929
+ {
7930
+ hasChanges: Type.Boolean({
7931
+ description: "Whether the initiative content should be updated (ignored if task has no initiative)"
7932
+ }),
7933
+ updatedContent: Type.Optional(
7934
+ Type.String({
7935
+ description: "Full updated initiative content markdown (required if hasChanges=true)"
7936
+ })
7937
+ )
7938
+ },
7939
+ {
7940
+ description: "Initiative content update \u2014 what was learned about this specific area of focus. Ignored if the task has no initiative_id."
7941
+ }
7858
7942
  )
7859
7943
  })
7860
7944
  }
@@ -8420,14 +8504,22 @@ var deskFreePlugin = {
8420
8504
  };
8421
8505
 
8422
8506
  // src/context.ts
8423
- var DESKFREE_AGENT_DIRECTIVE = `## DeskFree
8424
- Always read the deskfree skill (SKILL.md) at startup. Follow its workflow for task tracking and messaging.
8425
- 1. ALL work requires a task \u2014 use \`deskfree_create_task\` then \`deskfree_start_task\`.
8426
- 2. Ways of Working is your evolving playbook \u2014 it's injected automatically via state.get. When tasks are approved by humans, you'll evaluate them and update the ways of working.
8427
- 3. Build deliverables incrementally \u2014 use \`deskfree_update_deliverable\` from the start.
8428
- 4. Always complete tasks \u2014 use \`deskfree_complete_task\` with outcome "done" or "blocked".
8429
- 5. Auto-threading works \u2014 messages sent while a task is active are threaded automatically.
8430
- 6. Sub-agents get 4 tools: update_deliverable, complete_task, send_message (also supports suggestions), submit_evaluation.`;
8507
+ var DESKFREE_AGENT_DIRECTIVE = `## DeskFree \u2014 The Work Loop
8508
+ Always read the deskfree skill (SKILL.md) at startup. Follow the suggest-first work loop:
8509
+ 1. **Check state** \u2192 \`deskfree_state\` \u2014 see what needs attention, read ways of working.
8510
+ 2. **Suggest tasks** \u2192 \`deskfree_suggest_tasks\` \u2014 ALL work requires human-approved tasks first.
8511
+ 3. **Claim a task** \u2192 \`deskfree_start_task\` \u2014 read instructions + parent context carefully.
8512
+ 4. **Do the work** \u2192 \`deskfree_update_deliverable\` incrementally from the start.
8513
+ 5. **Suggest follow-ups** \u2192 if work reveals more to do, suggest them (strongest when you have full context).
8514
+ 6. **Complete** \u2192 \`deskfree_complete_task\` \u2014 deliverable required for "done".
8515
+ 7. **Evaluate** \u2192 check \`pendingEvaluations\` and update ways of working.
8516
+
8517
+ Key principles:
8518
+ - You're building a chain. Your instructions become someone else's brief. Your deliverable becomes someone else's context.
8519
+ - Write instructions as if briefing a contractor who has never seen the codebase.
8520
+ - MUST update deliverable before completing with outcome "done".
8521
+ - Estimate token cost per suggestion \u2014 consider files to read, reasoning, output.
8522
+ - Sub-agents get 4 tools: update_deliverable, complete_task, send_message, submit_evaluation.`;
8431
8523
  function getDeskFreeContext() {
8432
8524
  return `${DESKFREE_AGENT_DIRECTIVE}
8433
8525
 
@@ -8634,37 +8726,6 @@ function createOrchestratorTools(api) {
8634
8726
  }
8635
8727
  }
8636
8728
  },
8637
- {
8638
- ...ORCHESTRATOR_TOOLS.CREATE_TASK,
8639
- async execute(_id, params) {
8640
- try {
8641
- const title = validateStringParam(params, "title", true);
8642
- const instructions = validateStringParam(
8643
- params,
8644
- "instructions",
8645
- false
8646
- );
8647
- const task = await client.createTask({
8648
- title,
8649
- instructions
8650
- });
8651
- await client.sendMessage({
8652
- content: `\u{1F4CB} Created task: "${task.title}"`
8653
- }).catch(() => {
8654
- });
8655
- return formatTaskResponse(
8656
- task,
8657
- `Created task "${task.title}" with ID ${task.taskId}`,
8658
- [
8659
- "Claim and start this task with deskfree_start_task",
8660
- "Or check workspace state with deskfree_state"
8661
- ]
8662
- );
8663
- } catch (err) {
8664
- return errorResult(err);
8665
- }
8666
- }
8667
- },
8668
8729
  {
8669
8730
  ...ORCHESTRATOR_TOOLS.START_TASK,
8670
8731
  async execute(_id, params) {
@@ -8806,6 +8867,95 @@ function createOrchestratorTools(api) {
8806
8867
  }
8807
8868
  }
8808
8869
  },
8870
+ {
8871
+ ...ORCHESTRATOR_TOOLS.SUGGEST_TASKS,
8872
+ async execute(_id, params) {
8873
+ try {
8874
+ const rawSuggestions = params?.suggestions;
8875
+ if (!Array.isArray(rawSuggestions) || rawSuggestions.length === 0) {
8876
+ throw new Error(
8877
+ 'Parameter "suggestions" must be a non-empty array'
8878
+ );
8879
+ }
8880
+ const suggestions = rawSuggestions.map((s, i) => {
8881
+ if (typeof s !== "object" || s === null) {
8882
+ throw new Error(`suggestions[${i}] must be an object`);
8883
+ }
8884
+ const item = s;
8885
+ const title = item["title"];
8886
+ if (typeof title !== "string" || title.trim() === "") {
8887
+ throw new Error(
8888
+ `suggestions[${i}].title must be a non-empty string`
8889
+ );
8890
+ }
8891
+ return {
8892
+ title: title.trim(),
8893
+ instructions: typeof item["instructions"] === "string" ? item["instructions"] : void 0,
8894
+ estimatedTokens: typeof item["estimatedTokens"] === "number" ? item["estimatedTokens"] : void 0,
8895
+ dependsOn: Array.isArray(item["dependsOn"]) ? item["dependsOn"] : void 0,
8896
+ initiativeId: typeof item["initiativeId"] === "string" ? item["initiativeId"] : void 0
8897
+ };
8898
+ });
8899
+ const parentTaskId = validateStringParam(
8900
+ params,
8901
+ "parentTaskId",
8902
+ false
8903
+ );
8904
+ const rawInitiativeSuggestions = params?.initiativeSuggestions;
8905
+ let initiativeSuggestions;
8906
+ if (Array.isArray(rawInitiativeSuggestions) && rawInitiativeSuggestions.length > 0) {
8907
+ initiativeSuggestions = rawInitiativeSuggestions.map(
8908
+ (s, i) => {
8909
+ if (typeof s !== "object" || s === null) {
8910
+ throw new Error(`initiativeSuggestions[${i}] must be an object`);
8911
+ }
8912
+ const item = s;
8913
+ const title = item["title"];
8914
+ if (typeof title !== "string" || title.trim() === "") {
8915
+ throw new Error(
8916
+ `initiativeSuggestions[${i}].title must be a non-empty string`
8917
+ );
8918
+ }
8919
+ const content = item["content"];
8920
+ if (typeof content !== "string") {
8921
+ throw new Error(
8922
+ `initiativeSuggestions[${i}].content must be a string`
8923
+ );
8924
+ }
8925
+ return {
8926
+ title: title.trim(),
8927
+ content,
8928
+ taskRefs: Array.isArray(item["taskRefs"]) ? item["taskRefs"] : void 0
8929
+ };
8930
+ }
8931
+ );
8932
+ }
8933
+ const result = await client.suggestTasksDedicated({
8934
+ suggestions,
8935
+ parentTaskId,
8936
+ initiativeSuggestions
8937
+ });
8938
+ const initiativeCount = initiativeSuggestions?.length ?? 0;
8939
+ const summaryParts = [
8940
+ `Suggested ${suggestions.length} task${suggestions.length === 1 ? "" : "s"} for human approval`,
8941
+ ...initiativeCount > 0 ? [
8942
+ `and ${initiativeCount} initiative${initiativeCount === 1 ? "" : "s"}`
8943
+ ] : []
8944
+ ];
8945
+ return formatConfirmation(
8946
+ summaryParts.join(" "),
8947
+ [
8948
+ 'Tasks created with "suggested" status \u2014 human will approve or reject each',
8949
+ ...initiativeCount > 0 ? ["Initiative suggestions created \u2014 human will approve or reject independently"] : [],
8950
+ "Use deskfree_state to check for approved tasks"
8951
+ ],
8952
+ result
8953
+ );
8954
+ } catch (err) {
8955
+ return errorResult(err);
8956
+ }
8957
+ }
8958
+ },
8809
8959
  {
8810
8960
  ...ORCHESTRATOR_TOOLS.CLAIM_EVALUATION,
8811
8961
  async execute(_id, params) {
@@ -8826,14 +8976,15 @@ function createOrchestratorTools(api) {
8826
8976
  {
8827
8977
  summary: `Claimed evaluation for task "${result.task.title}"`,
8828
8978
  nextActions: [
8829
- "Review the task messages and current ways of working",
8830
- "Decide if patterns/learnings should update ways of working",
8979
+ "Review the task messages, current global ways of working, and initiative content (if present)",
8980
+ "Decide what to update: globalWoW (universal patterns), initiative (area-specific learnings), both, or neither",
8831
8981
  "Call deskfree_submit_evaluation with your analysis"
8832
8982
  ],
8833
8983
  task: result.task,
8834
8984
  waysOfWorking: result.waysOfWorking,
8835
8985
  currentVersion: result.currentVersion,
8836
- messages: result.messages
8986
+ messages: result.messages,
8987
+ ...result.initiative ? { initiative: result.initiative } : {}
8837
8988
  },
8838
8989
  null,
8839
8990
  2
@@ -8852,26 +9003,53 @@ function createOrchestratorTools(api) {
8852
9003
  try {
8853
9004
  const taskId = validateStringParam(params, "taskId", true);
8854
9005
  const reasoning = validateStringParam(params, "reasoning", true);
8855
- const hasChanges = params?.hasChanges;
8856
- if (typeof hasChanges !== "boolean") {
8857
- throw new Error('Parameter "hasChanges" must be a boolean');
9006
+ const rawGlobalWoW = params?.globalWoW;
9007
+ if (typeof rawGlobalWoW !== "object" || rawGlobalWoW === null) {
9008
+ throw new Error('Parameter "globalWoW" must be an object');
8858
9009
  }
8859
- const updatedContent = validateStringParam(
8860
- params,
8861
- "updatedContent",
8862
- false
8863
- );
9010
+ const globalWoWObj = rawGlobalWoW;
9011
+ if (typeof globalWoWObj["hasChanges"] !== "boolean") {
9012
+ throw new Error('Parameter "globalWoW.hasChanges" must be a boolean');
9013
+ }
9014
+ const globalWoW = {
9015
+ hasChanges: globalWoWObj["hasChanges"],
9016
+ updatedContent: typeof globalWoWObj["updatedContent"] === "string" ? globalWoWObj["updatedContent"] : void 0
9017
+ };
9018
+ const rawInitiative = params?.initiative;
9019
+ if (typeof rawInitiative !== "object" || rawInitiative === null) {
9020
+ throw new Error('Parameter "initiative" must be an object');
9021
+ }
9022
+ const initiativeObj = rawInitiative;
9023
+ if (typeof initiativeObj["hasChanges"] !== "boolean") {
9024
+ throw new Error('Parameter "initiative.hasChanges" must be a boolean');
9025
+ }
9026
+ const initiative = {
9027
+ hasChanges: initiativeObj["hasChanges"],
9028
+ updatedContent: typeof initiativeObj["updatedContent"] === "string" ? initiativeObj["updatedContent"] : void 0
9029
+ };
8864
9030
  const result = await client.submitEvaluation({
8865
9031
  taskId,
8866
9032
  reasoning,
8867
- hasChanges,
8868
- updatedContent
9033
+ globalWoW,
9034
+ initiative
8869
9035
  });
8870
- const messageContent = hasChanges ? `\u{1F4DD} Updated ways of working (v${result.version}): ${reasoning}` : `\u{1F4DD} No updates to ways of working: ${reasoning}`;
9036
+ const parts = [];
9037
+ if (globalWoW.hasChanges) {
9038
+ parts.push(`global WoW \u2192 v${result.globalVersion}`);
9039
+ }
9040
+ if (initiative.hasChanges && result.initiativeVersion !== void 0) {
9041
+ parts.push(`initiative \u2192 v${result.initiativeVersion}`);
9042
+ }
9043
+ const messageContent = parts.length > 0 ? `\u{1F4DD} Updated ${parts.join(", ")}: ${reasoning}` : `\u{1F4DD} No updates to ways of working: ${reasoning}`;
8871
9044
  await client.sendMessage({ content: messageContent, taskId }).catch(() => {
8872
9045
  });
9046
+ const summaryParts = [];
9047
+ if (globalWoW.hasChanges) summaryParts.push(`global WoW v${result.globalVersion}`);
9048
+ if (initiative.hasChanges && result.initiativeVersion !== void 0) {
9049
+ summaryParts.push(`initiative v${result.initiativeVersion}`);
9050
+ }
8873
9051
  return formatConfirmation(
8874
- hasChanges ? `Ways of working updated to v${result.version}` : "Evaluation complete \u2014 no changes needed",
9052
+ summaryParts.length > 0 ? `Evaluation complete \u2014 updated ${summaryParts.join(", ")}` : "Evaluation complete \u2014 no changes needed",
8875
9053
  ["Use deskfree_state to check for other pending evaluations"],
8876
9054
  result
8877
9055
  );