brainclaw 1.22.0 → 1.23.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.
Binary file
@@ -1,3 +1,4 @@
1
+ import { runMemoryConfirm } from '../commands/memory-confirm.js';
1
2
  import { runDecision } from '../commands/decision.js';
2
3
  import { runConstraint } from '../commands/constraint.js';
3
4
  import { runTrap } from '../commands/trap.js';
@@ -205,5 +206,19 @@ export function registerCaptureCommands(program) {
205
206
  .action((options) => {
206
207
  runRuntimeStatus(options);
207
208
  });
209
+ // --- confirm (pln#620) ---
210
+ // La surface qui manquait a `recordMemoryEvent` : le coeur existait, teste, branche sur
211
+ // un schema porte par les traps/decisions/contraintes — et n'etait appele DEPUIS NULLE
212
+ // PART. 0 item sur 471 portait la moindre confirmation au moment ou cette commande a ete
213
+ // ajoutee. C'est la classe de defaut de trp#1292 : un coeur vert, une fonctionnalite inerte.
214
+ program
215
+ .command('confirm <entity> <id> <kind>')
216
+ .description("Attester l'applicabilite d'un item de memoire : trap|decision|constraint, kind = confirm|infirm|saved_me|misled_me")
217
+ .option('--evidence <ref>', 'Preuve : fichier:ligne, sha de commit, sortie de commande (OBLIGATOIRE pour confirm)')
218
+ .option('--note <text>', 'Le « pourquoi » en une ligne')
219
+ .option('--json', 'Sortie JSON')
220
+ .action((entity, id, kind, options) => {
221
+ runMemoryConfirm({ entity, id, kind, evidence: options.evidence, note: options.note, json: options.json });
222
+ });
208
223
  }
209
224
  //# sourceMappingURL=register-capture.js.map
@@ -302,7 +302,6 @@ export async function handleBclawLoop(options) {
302
302
  slot_id: req.slot_id,
303
303
  role: req.role,
304
304
  input: req.input,
305
- dispatch: req.dispatch,
306
305
  assignment_id: req.assignment_id,
307
306
  claim_id: req.claim_id,
308
307
  actor,
@@ -11,30 +11,11 @@
11
11
  * @module
12
12
  */
13
13
  import { generatedSchemas } from './mcp-schemas.generated.js';
14
- const SEQUENCE_ITEM_INPUT_SCHEMA = {
15
- type: 'object',
16
- description: 'Sequence lane item. planId is required; stepId optionally narrows dispatch/readiness to a specific plan step.',
17
- properties: {
18
- planId: { type: 'string', minLength: 1, description: 'Plan item ID referenced by this sequence item.' },
19
- stepId: { type: 'string', minLength: 1, description: 'Optional plan step ID inside planId for step-level dispatch/readiness.' },
20
- rank: { type: 'number', minimum: 1, description: 'Positive integer ordering key. Ranks must be unique within a sequence.' },
21
- hard_after: {
22
- type: 'array',
23
- items: { type: 'string' },
24
- description: 'Sequence item planId values that must complete before this item becomes ready.',
25
- },
26
- soft_after: {
27
- type: 'array',
28
- items: { type: 'string' },
29
- description: 'Advisory predecessor planId values; they inform ordering but do not block readiness.',
30
- },
31
- lane: { type: 'string', description: 'Optional lane label used for parallel dispatch grouping and filtering.' },
32
- scope_hint: { type: 'string', description: 'Optional file/path scope hint for claim and brief generation.' },
33
- rationale: { type: 'string', description: 'Optional explanation for this item or dependency placement.' },
34
- },
35
- required: ['planId', 'rank'],
36
- additionalProperties: false,
37
- };
14
+ // SEQUENCE_ITEM_INPUT_SCHEMA a ete RETIRE (pln#599 batch 2). Ce sous-schema JSON manuel
15
+ // etait reutilise par create_sequence et update_sequence ; il est desormais derive d'une
16
+ // source zod UNIQUE (src/core/sequence-request-schema.ts) et materialise dans
17
+ // mcp-schemas.generated.ts. C'est exactement la classe de defaut de trp#180 — un
18
+ // sous-schema duplique, corrige d'un cote seulement qui disparait avec lui.
38
19
  const { $defs: loopPhaseDefs, ...loopPhaseItemSchema } = generatedSchemas.LoopPhase;
39
20
  const loopSlotInputItemSchema = generatedSchemas.LoopSlotInput;
40
21
  export const MCP_READ_TOOLS = [
@@ -159,21 +140,7 @@ export const MCP_READ_TOOLS = [
159
140
  name: 'bclaw_assignment_events',
160
141
  description: 'List correlated runtime events for assignments and runs with filters on assignment, run, claim, session, agent, or event type.',
161
142
  annotations: { tier: 'standard', category: 'coordination', headlessApproval: 'auto' },
162
- inputSchema: {
163
- type: 'object',
164
- properties: {
165
- assignmentId: { type: 'string', description: 'Filter by linked assignment ID.' },
166
- runId: { type: 'string', description: 'Filter by linked run ID.' },
167
- claimId: { type: 'string', description: 'Filter by linked claim ID.' },
168
- sessionId: { type: 'string', description: 'Filter by runtime session ID.' },
169
- agent: { type: 'string', description: 'Filter by agent name.' },
170
- eventType: { type: 'string', description: 'Filter by runtime event type.' },
171
- id: { type: 'string', description: 'Get a single runtime event by ID.' },
172
- limit: { type: 'number', description: 'Maximum number of events to return (default: 20).' },
173
- offset: { type: 'number', description: 'Number of events to skip (for pagination).' },
174
- compact: { type: 'boolean', description: 'Return only key fields to reduce output size.' },
175
- },
176
- },
143
+ inputSchema: { ...generatedSchemas.AssignmentEventsRequest },
177
144
  },
178
145
  {
179
146
  name: 'bclaw_list_agents',
@@ -553,36 +520,18 @@ const MCP_WRITE_TOOLS = [
553
520
  {
554
521
  name: 'bclaw_write_note',
555
522
  description: 'Add a runtime note. Requires contributor trust level or above. Use crossProject to push a runtime-note signal to a linked project (requires role: publisher in cross_project_links config).',
556
- annotations: { tier: 'standard', category: 'memory', headlessApproval: 'auto' },
523
+ annotations: { tier: 'standard', category: 'memory', headlessApproval: 'auto', schemaSource: 'zod-derived' },
557
524
  inputSchema: {
558
- type: 'object',
559
- properties: {
560
- text: { type: 'string', description: 'Note content.' },
561
- agent: { type: 'string', description: 'Agent name.' },
562
- agentId: { type: 'string', description: 'Registered agent id.' },
563
- tags: { type: 'array', items: { type: 'string' }, description: 'Optional tags.' },
564
- visibility: { type: 'string', description: 'Visibility: shared, machine, private.' },
565
- ttl: { type: 'string', description: 'Optional TTL: 30m, 2h, 7d.' },
566
- autoReflect: { type: 'boolean', description: 'Attempt to reflect the runtime note into durable memory immediately.' },
567
- crossProject: { type: 'string', description: 'Push note to a linked project (name or path). Requires role: publisher in cross_project_links config.' },
568
- cross_project: { type: 'string', description: 'Snake_case alias of crossProject.' },
569
- },
525
+ ...generatedSchemas.WriteNoteRequest,
570
526
  required: ['text'],
571
527
  },
572
528
  },
573
529
  {
574
530
  name: 'bclaw_quick_capture',
575
531
  description: 'Capture free-form text as a decision, trap, constraint, or runtime note. Declare `type` yourself (you know what you are capturing — caller assertion wins); keyword heuristics are only a fallback when type is absent. Contradictions with existing memory are attached as advisory metadata on the candidate, never block promotion.',
576
- annotations: { tier: 'standard', category: 'memory', headlessApproval: 'auto' },
532
+ annotations: { tier: 'standard', category: 'memory', headlessApproval: 'auto', schemaSource: 'zod-derived' },
577
533
  inputSchema: {
578
- type: 'object',
579
- properties: {
580
- text: { type: 'string', description: 'Free-form capture text.' },
581
- type: { type: 'string', enum: ['decision', 'trap', 'constraint', 'note'], description: 'Caller-asserted classification. Strongly recommended — the calling agent knows the nature of the capture better than keyword heuristics (cnd_abe61d68: 18 false contradiction positives on a review summary).' },
582
- context: { type: 'string', description: 'Optional file/path/scope context to associate with the capture.' },
583
- agent: { type: 'string', description: 'Agent name.' },
584
- agentId: { type: 'string', description: 'Registered agent id.' },
585
- },
534
+ ...generatedSchemas.QuickCaptureRequest,
586
535
  required: ['text'],
587
536
  },
588
537
  },
@@ -590,116 +539,41 @@ const MCP_WRITE_TOOLS = [
590
539
  name: 'bclaw_claim',
591
540
  description: 'Claim a work scope (advisory lock). By default creates an isolated git worktree for the claim (multi-agent safety). Pass advisory:true (or worktree:false) for an advisory-only lock with NO worktree — use this when the work already lives uncommitted in the main tree and a fresh worktree would be counterproductive (trp#431). Requires contributor trust level or above.',
592
541
  annotations: { tier: 'standard', category: 'coordination', headlessApproval: 'auto' },
593
- inputSchema: {
594
- type: 'object',
595
- properties: {
596
- scope: { type: 'string', description: 'Scope being claimed.' },
597
- description: { type: 'string', description: 'Description of the work.' },
598
- agent: { type: 'string', description: 'Agent or person name.' },
599
- agentId: { type: 'string', description: 'Registered agent id.' },
600
- planId: { type: 'string', description: 'Optional linked plan item ID.' },
601
- project: { type: 'string', description: 'Project name or path. Use this when working on a project different from the MCP server workspace (e.g. CLI agents in a different directory).' },
602
- store: { type: 'string', description: 'Target store level: local (default), repo, workspace.' },
603
- worktreeBranch: { type: 'string', description: 'Branch name for the worktree. Defaults to feat/<scope-slug>.' },
604
- worktree: { type: 'boolean', description: 'Whether to create an isolated git worktree (default true). Pass false for an advisory-only lock with no worktree (trp#431) — for in-place work in the main tree.' },
605
- advisory: { type: 'boolean', description: 'Alias for worktree:false — advisory-only lock with no worktree (trp#431).' },
606
- handoffMode: { type: 'string', enum: ['self-commit', 'integrator'], description: 'Handoff mode: "self-commit" (worker commits+merges) or "integrator" (another agent reviews+merges). Default: self-commit.' },
607
- },
608
- required: ['scope', 'description'],
609
- },
542
+ inputSchema: { ...generatedSchemas.ClaimRequest },
610
543
  },
611
544
  {
612
545
  name: 'bclaw_release_claim',
613
546
  description: 'Release a work claim. Callers own their own claims; a trusted+ coordinator releasing another agent\'s claim MUST pass coordinator_override:true (audited).',
614
547
  annotations: { tier: 'standard', category: 'coordination', headlessApproval: 'auto' },
615
- inputSchema: {
616
- type: 'object',
617
- properties: {
618
- id: { type: 'string', description: 'Claim ID to release.' },
619
- planStatus: { type: 'string', description: 'Optional: update linked plan status.' },
620
- coordinator_override: {
621
- type: 'boolean',
622
- description: 'Opt-in override for a trusted+ caller releasing a claim they do NOT own (cross-agent teardown, ghost-claim cleanup). Rejected for contributor-level callers; audited when used. trp#928.',
623
- },
624
- },
625
- required: ['id'],
626
- },
548
+ inputSchema: { ...generatedSchemas.ReleaseClaimRequest },
627
549
  },
628
550
  {
629
551
  name: 'bclaw_session_start',
630
552
  description: 'Start a session and capture initial context. Pass includeContext and/or includeBoard to get full context + agent board in a single call, eliminating the need for separate bclaw_get_context and bclaw_get_agent_board calls.',
631
553
  annotations: { tier: 'standard', category: 'session', headlessApproval: 'auto' },
632
- inputSchema: {
633
- type: 'object',
634
- properties: {
635
- agent: { type: 'string', description: 'Agent name.' },
636
- agentId: { type: 'string', description: 'Registered agent id.' },
637
- context: { type: 'string', description: 'Context target path.' },
638
- maintenanceMode: { type: 'string', enum: ['fast', 'full'], description: 'Maintenance mode. Default is full for explicit session-start calls; use fast to skip non-critical maintenance work.' },
639
- includeContext: { type: 'boolean', description: 'Include project memory context in the response (equivalent to bclaw_get_context).' },
640
- includeBoard: { type: 'boolean', description: 'Include agent board (plans, claims, handoffs) in the response (equivalent to bclaw_get_agent_board).' },
641
- contextProfile: { type: 'string', description: 'Context profile when includeContext is true: dev (default), dense, compact, copilot, quick, briefing, openclaw, ops, research. If unset, uses the agent default profile.' },
642
- contextFormat: { type: 'string', description: 'Context format when includeContext is true: markdown, json, or template.' },
643
- },
644
- },
554
+ inputSchema: { ...generatedSchemas.SessionStartRequest },
645
555
  },
646
556
  {
647
557
  name: 'bclaw_session_end',
648
558
  description: 'End a session and optionally auto-reflect observations as candidates.',
649
559
  annotations: { tier: 'standard', category: 'session', headlessApproval: 'auto' },
650
- inputSchema: {
651
- type: 'object',
652
- properties: {
653
- session: { type: 'string', description: 'Session ID.' },
654
- agent: { type: 'string', description: 'Agent name.' },
655
- agentId: { type: 'string', description: 'Registered agent id.' },
656
- summary: { type: 'string', description: 'Session summary text.' },
657
- narrative: { type: 'string', description: 'Free-text narrative of what happened in the session and why. Goes beyond the auto-generated commit list: "Tried X, failed because Y, pivoted to Z. Watch out for A."' },
658
- autoReflect: { type: 'boolean', description: 'Auto-reflect session notes as candidates.' },
659
- autoRelease: { type: 'boolean', description: 'Auto-release any active claims at session end.' },
660
- reflectHandoff: { type: 'boolean', description: 'Materialize an open handoff from git commits since session start.' },
661
- dispatchReview: { type: 'boolean', description: 'When used with reflectHandoff, auto-dispatch a code review if the reflected handoff is reviewable.' },
662
- reviewer: { type: 'string', description: 'Explicit reviewer for the reflected handoff review dispatch.' },
663
- reflect: { type: 'boolean', description: 'Emit the dogfooding reflection prompt (project + your surfaces/skills/tools). Default true — pass false to suppress on a trivial session. Capture actionable findings via bclaw_quick_capture.' },
664
- },
665
- },
560
+ inputSchema: { ...generatedSchemas.SessionEndRequest },
666
561
  },
667
562
  {
668
563
  name: 'bclaw_create_sequence',
669
564
  description: 'Create a coordination sequence shared by agents.',
670
- annotations: { tier: 'standard', category: 'coordination', headlessApproval: 'prompt' },
565
+ annotations: { tier: 'standard', category: 'coordination', headlessApproval: 'prompt', schemaSource: 'zod-derived' },
671
566
  inputSchema: {
672
- type: 'object',
673
- properties: {
674
- name: { type: 'string', description: 'Sequence name.' },
675
- description: { type: 'string', description: 'Optional sequence description.' },
676
- status: { type: 'string', description: 'Status: draft, active, archived.' },
677
- owner: { type: 'string', description: 'Optional sequence owner.' },
678
- items: { type: 'array', description: 'Sequence items in rank order.', items: SEQUENCE_ITEM_INPUT_SCHEMA },
679
- tags: { type: 'array', items: { type: 'string' }, description: 'Optional tags.' },
680
- agent: { type: 'string', description: 'Agent name.' },
681
- agentId: { type: 'string', description: 'Registered agent id.' },
682
- },
567
+ ...generatedSchemas.CreateSequenceRequest,
683
568
  required: ['name'],
684
569
  },
685
570
  },
686
571
  {
687
572
  name: 'bclaw_update_sequence',
688
573
  description: 'Update a coordination sequence status, metadata, or items.',
689
- annotations: { tier: 'standard', category: 'coordination', headlessApproval: 'prompt' },
574
+ annotations: { tier: 'standard', category: 'coordination', headlessApproval: 'prompt', schemaSource: 'zod-derived' },
690
575
  inputSchema: {
691
- type: 'object',
692
- properties: {
693
- id: { type: 'string', description: 'Sequence ID or short label.' },
694
- name: { type: 'string', description: 'Optional new sequence name.' },
695
- description: { type: 'string', description: 'Optional new description.' },
696
- status: { type: 'string', description: 'Status: draft, active, archived.' },
697
- owner: { type: 'string', description: 'Optional sequence owner.' },
698
- items: { type: 'array', description: 'Optional replacement items array.', items: SEQUENCE_ITEM_INPUT_SCHEMA },
699
- tags: { type: 'array', items: { type: 'string' }, description: 'Optional replacement tags.' },
700
- agent: { type: 'string', description: 'Agent name.' },
701
- agentId: { type: 'string', description: 'Registered agent id.' },
702
- },
576
+ ...generatedSchemas.UpdateSequenceRequest,
703
577
  required: ['id'],
704
578
  },
705
579
  },
@@ -707,82 +581,25 @@ const MCP_WRITE_TOOLS = [
707
581
  name: 'bclaw_add_step',
708
582
  description: 'Add a sub-step to a plan item. Canonical shape is `{ planId, data: { text, title?, assignee? } }`; legacy top-level `{ text, assignee }` still works for backward compatibility. If both are present, data.* wins and a warning is emitted. Requires contributor trust level or above. Pass `project` to target a step in a plan that lives in a linked project (same pattern as the canonical-grammar tools).',
709
583
  annotations: { tier: 'standard', category: 'coordination', headlessApproval: 'auto' },
710
- inputSchema: {
711
- type: 'object',
712
- properties: {
713
- planId: { type: 'string', description: 'Plan item ID.' },
714
- data: {
715
- type: 'object',
716
- description: 'Canonical step payload: { text, title?, assignee? }. title is accepted as an alias for text.',
717
- properties: {
718
- text: { type: 'string', description: 'Step description.' },
719
- title: { type: 'string', description: 'Alias for text.' },
720
- assignee: { type: 'string', description: 'Optional assignee.' },
721
- estimated_effort: { type: 'number', description: 'Step-level estimate in minutes (pln#495). A duration string like "2h"/"30m" is also accepted and coerced.' },
722
- actual_effort: { type: 'string', description: 'Step-level actual effort, free-form ("45m", "2h"), parsed when the estimation report runs.' },
723
- },
724
- },
725
- text: { type: 'string', description: 'Legacy top-level step description; prefer data.text.' },
726
- agent: { type: 'string', description: 'Agent name.' },
727
- agentId: { type: 'string', description: 'Registered agent id.' },
728
- assignee: { type: 'string', description: 'Legacy top-level optional assignee; prefer data.assignee.' },
729
- project: { type: 'string', description: 'Optional: name (or path/basename) of a linked project to add the step in. Defaults to the current project. Same resolution as canonical-grammar tools — accepts cross_project_links and workspace store-chain children.' },
730
- },
731
- required: ['planId'],
732
- },
584
+ inputSchema: { ...generatedSchemas.AddStepRequest },
733
585
  },
734
586
  {
735
587
  name: 'bclaw_complete_step',
736
588
  description: 'Mark a plan sub-step as done. Requires contributor trust level or above. Pass `project` to operate on a plan in a linked project.',
737
589
  annotations: { tier: 'standard', category: 'coordination', headlessApproval: 'auto' },
738
- inputSchema: {
739
- type: 'object',
740
- properties: {
741
- planId: { type: 'string', description: 'Plan item ID.' },
742
- stepId: { type: 'string', description: 'Step ID to complete.' },
743
- agent: { type: 'string', description: 'Agent name.' },
744
- agentId: { type: 'string', description: 'Registered agent id.' },
745
- project: { type: 'string', description: 'Optional: name of a linked project to complete the step in. Defaults to the current project.' },
746
- },
747
- required: ['planId', 'stepId'],
748
- },
590
+ inputSchema: { ...generatedSchemas.CompleteStepRequest },
749
591
  },
750
592
  {
751
593
  name: 'bclaw_update_step',
752
594
  description: 'Update a plan sub-step (status, text, assignee). Supports all step statuses: todo, in_progress, testing, done, blocked. Requires contributor trust level or above. Pass `project` to operate on a plan in a linked project.',
753
595
  annotations: { tier: 'standard', category: 'coordination', headlessApproval: 'auto' },
754
- inputSchema: {
755
- type: 'object',
756
- properties: {
757
- planId: { type: 'string', description: 'Plan item ID.' },
758
- stepId: { type: 'string', description: 'Step ID to update.' },
759
- status: { type: 'string', description: 'New status: todo, in_progress, testing, done, blocked.' },
760
- text: { type: 'string', description: 'New step text.' },
761
- assignee: { type: 'string', description: 'New assignee (empty string to unassign).' },
762
- estimated_effort: { type: 'number', description: 'Step-level estimate in minutes (pln#495); a duration string is also coerced.' },
763
- actual_effort: { type: 'string', description: 'Step-level actual effort, free-form ("45m", "2h").' },
764
- agent: { type: 'string', description: 'Agent name.' },
765
- agentId: { type: 'string', description: 'Registered agent id.' },
766
- project: { type: 'string', description: 'Optional: name of a linked project to update the step in. Defaults to the current project.' },
767
- },
768
- required: ['planId', 'stepId'],
769
- },
596
+ inputSchema: { ...generatedSchemas.UpdateStepRequest },
770
597
  },
771
598
  {
772
599
  name: 'bclaw_delete_step',
773
600
  description: 'Remove a sub-step from a plan. Requires contributor trust level or above. Pass `project` to operate on a plan in a linked project.',
774
601
  annotations: { tier: 'standard', category: 'coordination', headlessApproval: 'prompt' },
775
- inputSchema: {
776
- type: 'object',
777
- properties: {
778
- planId: { type: 'string', description: 'Plan item ID.' },
779
- stepId: { type: 'string', description: 'Step ID to delete.' },
780
- agent: { type: 'string', description: 'Agent name.' },
781
- agentId: { type: 'string', description: 'Registered agent id.' },
782
- project: { type: 'string', description: 'Optional: name of a linked project to delete the step from. Defaults to the current project.' },
783
- },
784
- required: ['planId', 'stepId'],
785
- },
602
+ inputSchema: { ...generatedSchemas.DeleteStepRequest },
786
603
  },
787
604
  {
788
605
  name: 'bclaw_delete_plan',
@@ -1076,62 +893,13 @@ const MCP_WRITE_TOOLS = [
1076
893
  name: 'bclaw_assignment_update',
1077
894
  description: 'Report assignment lifecycle status. Part of the Agent SDK runtime protocol. Workers call this to report: accepted (acknowledging receipt), started (work begun), progress (heartbeat), completed (done with artifacts), failed (error), or blocked (external blocker). The assignment_id is provided in the dispatch brief. OWNERSHIP (trp#291): only the agent the assignment is OWNED BY (the dispatched worker) may update it — a different agent (e.g. the coordinator) gets `Agent <x> cannot update assignment owned by <y>`. If you are the coordinator and need to converge a worker run, do NOT call this; verify via bclaw_dispatch_status instead (the reconciler infers completion from sentinels/commits).',
1078
895
  annotations: { tier: 'standard', category: 'coordination', headlessApproval: 'auto' },
1079
- inputSchema: {
1080
- type: 'object',
1081
- properties: {
1082
- assignment_id: { type: 'string', description: 'Assignment ID from the dispatch brief (asgn_xxx).' },
1083
- status: { type: 'string', enum: ['accepted', 'started', 'progress', 'completed', 'failed', 'blocked'], description: 'Lifecycle status to report.' },
1084
- message: { type: 'string', description: 'Human-readable status message or progress note.' },
1085
- artifacts: {
1086
- type: 'array',
1087
- items: {
1088
- type: 'object',
1089
- properties: {
1090
- type: { type: 'string', description: 'Artifact type: commit, branch, file, pr, test_result.' },
1091
- ref: { type: 'string', description: 'Reference: SHA, branch name, file path, PR URL.' },
1092
- description: { type: 'string', description: 'Optional description.' },
1093
- },
1094
- required: ['type', 'ref'],
1095
- },
1096
- description: 'Artifacts produced. Most useful for completed status.',
1097
- },
1098
- error_message: { type: 'string', description: 'Error details (for failed status).' },
1099
- blocker: { type: 'string', description: 'Blocker description (for blocked status).' },
1100
- action_required: {
1101
- type: 'object',
1102
- description: 'Optional ActionRequired payload when status=blocked. Lets the worker request approval, user input, or clarification before resuming.',
1103
- properties: {
1104
- kind: { type: 'string', enum: ['approval', 'user_input', 'clarification', 'plan_approval'], description: 'Kind of action needed.' },
1105
- title: { type: 'string', description: 'Short title shown to supervisors/UI.' },
1106
- prompt: { type: 'string', description: 'Question or approval prompt to answer.' },
1107
- options: { type: 'array', items: { type: 'string' }, description: 'Optional answer choices.' },
1108
- response_schema: { type: 'object', description: 'Optional structured response schema hint.' },
1109
- tags: { type: 'array', items: { type: 'string' }, description: 'Optional tags.' },
1110
- },
1111
- required: ['kind', 'title', 'prompt'],
1112
- },
1113
- agent: { type: 'string', description: 'Agent name.' },
1114
- agentId: { type: 'string', description: 'Registered agent id.' },
1115
- },
1116
- required: ['assignment_id', 'status'],
1117
- },
896
+ inputSchema: { ...generatedSchemas.AssignmentUpdateRequest },
1118
897
  },
1119
898
  {
1120
899
  name: 'bclaw_assignment_action',
1121
900
  description: 'Resolve or reject a pending ActionRequired item and update the linked Assignment/AgentRun state.',
1122
901
  annotations: { tier: 'standard', category: 'coordination', headlessApproval: 'auto' },
1123
- inputSchema: {
1124
- type: 'object',
1125
- properties: {
1126
- action_id: { type: 'string', description: 'ActionRequired ID (act_xxx).' },
1127
- outcome: { type: 'string', enum: ['resolved', 'rejected', 'cancelled'], description: 'How the supervisor resolves the pending action.' },
1128
- text: { type: 'string', description: 'Human-readable response or rationale.' },
1129
- payload: { type: 'object', description: 'Optional structured response payload.' },
1130
- agent: { type: 'string', description: 'Supervisor/agent responding to the action.' },
1131
- agentId: { type: 'string', description: 'Registered agent id.' },
1132
- },
1133
- required: ['action_id', 'outcome'],
1134
- },
902
+ inputSchema: { ...generatedSchemas.AssignmentActionRequest },
1135
903
  },
1136
904
  {
1137
905
  name: 'bclaw_harvest_candidates',
@@ -737,7 +737,11 @@ function dispatchReadTool(name, args, ctx) {
737
737
  ...(bounded.next_offset !== undefined ? { next_offset: bounded.next_offset } : {}),
738
738
  ...(bounded.omitted_for_size ? { omitted_for_size: bounded.omitted_for_size } : {}),
739
739
  ...(bounded.hint ? { hint: bounded.hint } : {}),
740
- next_actions: nextActions,
740
+ // OMETTRE la cle plutot que rendre un tableau vide (pln#598 etape 4). La regle de
741
+ // src/core/next-actions.ts est explicite : « les appelants omettent entierement la
742
+ // cle quand le tableau est vide ». Un next_actions vide est le pire des deux
743
+ // mondes — le champ existe, ne dit rien, et apprend quand meme a l ignorer.
744
+ ...(nextActions.length ? { next_actions: nextActions } : {}),
741
745
  },
742
746
  };
743
747
  }