brainclaw 0.28.0 → 1.5.3

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 (198) hide show
  1. package/README.md +193 -170
  2. package/dist/brainclaw-vscode.vsix +0 -0
  3. package/dist/cli.js +683 -23
  4. package/dist/commands/accept.js +3 -0
  5. package/dist/commands/add-step.js +11 -26
  6. package/dist/commands/agent-board.js +70 -3
  7. package/dist/commands/audit.js +19 -0
  8. package/dist/commands/check-policy.js +54 -0
  9. package/dist/commands/check-security-mcp.js +145 -0
  10. package/dist/commands/check-security.js +106 -0
  11. package/dist/commands/claim-resource.js +1 -0
  12. package/dist/commands/codev.js +672 -0
  13. package/dist/commands/compact.js +74 -0
  14. package/dist/commands/complete-step.js +16 -26
  15. package/dist/commands/constraint.js +8 -20
  16. package/dist/commands/decision.js +9 -20
  17. package/dist/commands/delete-plan.js +10 -12
  18. package/dist/commands/delete-step.js +16 -0
  19. package/dist/commands/dispatch.js +163 -0
  20. package/dist/commands/doctor.js +1122 -49
  21. package/dist/commands/enable-agent.js +1 -0
  22. package/dist/commands/export.js +280 -22
  23. package/dist/commands/handoff.js +33 -0
  24. package/dist/commands/harvest.js +189 -0
  25. package/dist/commands/hooks.js +82 -25
  26. package/dist/commands/inbox.js +169 -0
  27. package/dist/commands/init.js +38 -31
  28. package/dist/commands/install-hooks.js +71 -44
  29. package/dist/commands/link.js +89 -0
  30. package/dist/commands/list-claims.js +48 -3
  31. package/dist/commands/list-plans.js +129 -25
  32. package/dist/commands/loops-handlers.js +409 -0
  33. package/dist/commands/mcp-read-handlers.js +1628 -0
  34. package/dist/commands/mcp-schemas.generated.js +74 -0
  35. package/dist/commands/mcp.js +4244 -1475
  36. package/dist/commands/plan-resource.js +64 -0
  37. package/dist/commands/plan.js +12 -26
  38. package/dist/commands/prune.js +37 -2
  39. package/dist/commands/reflect.js +20 -7
  40. package/dist/commands/release-claim.js +11 -6
  41. package/dist/commands/release-notes.js +170 -0
  42. package/dist/commands/repair.js +210 -0
  43. package/dist/commands/run-profile.js +57 -0
  44. package/dist/commands/sequence.js +113 -0
  45. package/dist/commands/session-end.js +423 -14
  46. package/dist/commands/session-start.js +214 -41
  47. package/dist/commands/setup-security.js +103 -0
  48. package/dist/commands/setup.js +42 -4
  49. package/dist/commands/stale.js +109 -0
  50. package/dist/commands/switch.js +131 -10
  51. package/dist/commands/trap.js +14 -31
  52. package/dist/commands/update-handoff.js +63 -4
  53. package/dist/commands/update-plan.js +21 -28
  54. package/dist/commands/update-step.js +37 -0
  55. package/dist/commands/upgrade.js +313 -6
  56. package/dist/commands/usage.js +102 -0
  57. package/dist/commands/version.js +20 -0
  58. package/dist/commands/who.js +124 -0
  59. package/dist/commands/worktree.js +105 -0
  60. package/dist/core/actions.js +315 -0
  61. package/dist/core/agent-capability.js +610 -17
  62. package/dist/core/agent-context.js +7 -1
  63. package/dist/core/agent-files.js +1169 -85
  64. package/dist/core/agent-integrations.js +160 -5
  65. package/dist/core/agent-inventory.js +2 -0
  66. package/dist/core/agent-profiles.js +93 -0
  67. package/dist/core/agent-registry.js +162 -30
  68. package/dist/core/agentrun-reconciler.js +345 -0
  69. package/dist/core/agentruns.js +424 -0
  70. package/dist/core/ai-agent-detection.js +31 -10
  71. package/dist/core/archival.js +77 -0
  72. package/dist/core/assignment-sweeper.js +82 -0
  73. package/dist/core/assignments.js +367 -0
  74. package/dist/core/audit.js +30 -0
  75. package/dist/core/bootstrap.js +61 -10
  76. package/dist/core/brainclaw-version.js +94 -2
  77. package/dist/core/candidates.js +93 -2
  78. package/dist/core/claims.js +419 -0
  79. package/dist/core/codev-metrics.js +77 -0
  80. package/dist/core/codev-personas.js +31 -0
  81. package/dist/core/codev-plan-gen.js +35 -0
  82. package/dist/core/codev-prompts.js +74 -0
  83. package/dist/core/codev-responses.js +62 -0
  84. package/dist/core/codev-rounds.js +218 -0
  85. package/dist/core/config.js +4 -0
  86. package/dist/core/context.js +454 -34
  87. package/dist/core/coordination.js +201 -6
  88. package/dist/core/cross-project.js +230 -16
  89. package/dist/core/default-profiles/doctor.yaml +11 -0
  90. package/dist/core/default-profiles/janitor.yaml +11 -0
  91. package/dist/core/default-profiles/onboarder.yaml +11 -0
  92. package/dist/core/default-profiles/reviewer.yaml +13 -0
  93. package/dist/core/dispatcher.js +1189 -0
  94. package/dist/core/duplicates.js +2 -2
  95. package/dist/core/entity-operations.js +450 -0
  96. package/dist/core/entity-registry.js +344 -0
  97. package/dist/core/event-log.js +1 -0
  98. package/dist/core/events.js +106 -2
  99. package/dist/core/execution-adapters.js +154 -0
  100. package/dist/core/execution-context.js +63 -0
  101. package/dist/core/execution-profile.js +270 -0
  102. package/dist/core/execution.js +255 -0
  103. package/dist/core/facade-schema.js +81 -0
  104. package/dist/core/federation-cloud.js +99 -0
  105. package/dist/core/federation-message.js +52 -0
  106. package/dist/core/federation-transport.js +65 -0
  107. package/dist/core/gc-semantic.js +482 -0
  108. package/dist/core/governance.js +247 -0
  109. package/dist/core/guards.js +19 -0
  110. package/dist/core/ideation.js +72 -0
  111. package/dist/core/identity.js +252 -28
  112. package/dist/core/ids.js +6 -0
  113. package/dist/core/input-validation.js +2 -2
  114. package/dist/core/instruction-templates.js +344 -136
  115. package/dist/core/io.js +90 -11
  116. package/dist/core/lock.js +6 -2
  117. package/dist/core/loops/brief-assembly.js +213 -0
  118. package/dist/core/loops/facade-schema.js +148 -0
  119. package/dist/core/loops/index.js +7 -0
  120. package/dist/core/loops/iteration-engine.js +139 -0
  121. package/dist/core/loops/lock.js +385 -0
  122. package/dist/core/loops/store.js +201 -0
  123. package/dist/core/loops/types.js +403 -0
  124. package/dist/core/loops/verbs.js +534 -0
  125. package/dist/core/markdown.js +15 -3
  126. package/dist/core/memory-compactor.js +432 -0
  127. package/dist/core/memory-git.js +152 -8
  128. package/dist/core/messaging.js +278 -0
  129. package/dist/core/migration.js +32 -1
  130. package/dist/core/mutation-pipeline.js +4 -2
  131. package/dist/core/operations/memory-mutation.js +129 -0
  132. package/dist/core/operations/memory-write.js +78 -0
  133. package/dist/core/operations/plan.js +190 -0
  134. package/dist/core/policy.js +169 -0
  135. package/dist/core/repo-analysis.js +67 -0
  136. package/dist/core/reputation.js +9 -3
  137. package/dist/core/schema.js +546 -21
  138. package/dist/core/search.js +21 -2
  139. package/dist/core/security-cache.js +71 -0
  140. package/dist/core/security-guard.js +152 -0
  141. package/dist/core/security-scoring.js +86 -0
  142. package/dist/core/sequence.js +130 -0
  143. package/dist/core/socket-client.js +113 -0
  144. package/dist/core/staleness.js +246 -0
  145. package/dist/core/state.js +98 -22
  146. package/dist/core/store-resolution.js +54 -12
  147. package/dist/core/toml-writer.js +76 -0
  148. package/dist/core/upgrades/backup.js +232 -0
  149. package/dist/core/upgrades/health-check.js +169 -0
  150. package/dist/core/upgrades/patches/candidate-archive.js +145 -0
  151. package/dist/core/upgrades/patches/handoff-review-strip.js +128 -0
  152. package/dist/core/upgrades/patches/provenance-rollout.js +136 -0
  153. package/dist/core/upgrades/schema-version.js +97 -0
  154. package/dist/core/worktree.js +606 -0
  155. package/dist/facts.js +114 -0
  156. package/dist/facts.json +111 -0
  157. package/docs/architecture/project-refs.md +5 -1
  158. package/docs/cli.md +690 -43
  159. package/docs/concepts/ideation-loop.md +317 -0
  160. package/docs/concepts/loop-engine.md +456 -0
  161. package/docs/concepts/mcp-governance.md +268 -0
  162. package/docs/concepts/memory-staleness.md +122 -0
  163. package/docs/concepts/multi-agent-workflows.md +166 -0
  164. package/docs/concepts/plans-and-claims.md +31 -6
  165. package/docs/concepts/project-md-convention.md +35 -0
  166. package/docs/concepts/troubleshooting.md +220 -0
  167. package/docs/concepts/upgrade-cli.md +202 -0
  168. package/docs/concepts/upgrade-dogfood-procedure.md +114 -0
  169. package/docs/context-format-changelog.md +2 -2
  170. package/docs/context-format.md +2 -2
  171. package/docs/index.md +68 -0
  172. package/docs/integrations/agents.md +15 -16
  173. package/docs/integrations/cline.md +88 -0
  174. package/docs/integrations/codex.md +75 -23
  175. package/docs/integrations/continue.md +60 -0
  176. package/docs/integrations/copilot.md +67 -9
  177. package/docs/integrations/kilocode.md +72 -0
  178. package/docs/integrations/mcp.md +304 -21
  179. package/docs/integrations/mistral-vibe.md +122 -0
  180. package/docs/integrations/opencode.md +84 -0
  181. package/docs/integrations/overview.md +23 -8
  182. package/docs/integrations/roo.md +74 -0
  183. package/docs/integrations/windsurf.md +83 -0
  184. package/docs/mcp-schema-changelog.md +191 -1
  185. package/docs/playbooks/integration/index.md +121 -0
  186. package/docs/playbooks/productivity/index.md +102 -0
  187. package/docs/playbooks/team/index.md +122 -0
  188. package/docs/product/agent-first-model.md +184 -0
  189. package/docs/product/entity-model-audit.md +462 -0
  190. package/docs/quickstart-existing-project.md +135 -0
  191. package/docs/quickstart.md +124 -37
  192. package/docs/release-maintenance.md +79 -0
  193. package/docs/review.md +2 -0
  194. package/docs/server-operations.md +118 -0
  195. package/package.json +20 -12
  196. package/dist/commands/claude-desktop-extension.js +0 -18
  197. package/dist/commands/diff.js +0 -99
  198. package/dist/core/claude-desktop-extension.js +0 -224
@@ -33,16 +33,89 @@ function coerceEffortToMinutes(val) {
33
33
  }
34
34
  return undefined;
35
35
  }
36
+ /** Coerce tags from JSON string to array when MCP clients serialize arrays as strings.
37
+ * Accepts: string[] (passthrough), '["a","b"]' (JSON parse), 'a,b' (comma split). */
38
+ function coerceTags(val) {
39
+ if (Array.isArray(val))
40
+ return val;
41
+ if (typeof val === 'string') {
42
+ const trimmed = val.trim();
43
+ if (trimmed.startsWith('[')) {
44
+ try {
45
+ const parsed = JSON.parse(trimmed);
46
+ if (Array.isArray(parsed))
47
+ return parsed;
48
+ }
49
+ catch { /* fall through */ }
50
+ }
51
+ if (trimmed.length > 0)
52
+ return trimmed.split(',').map(t => t.trim()).filter(Boolean);
53
+ return [];
54
+ }
55
+ return val;
56
+ }
57
+ /** Resilient tags schema that accepts string[] or JSON-serialized string. */
58
+ export const TagsSchema = z.preprocess(coerceTags, z.array(z.string()));
59
+ export const TagsWithDefaultSchema = z.preprocess(coerceTags, z.array(z.string()).default([]));
36
60
  // --- Entry schemas ---
37
61
  export const ConstraintStatusSchema = z.enum(['active', 'resolved', 'expired']);
38
62
  export const ConstraintCategorySchema = z.enum(['architecture', 'performance', 'security', 'reliability', 'compatibility', 'process', 'other']);
39
63
  export const SeveritySchema = z.enum(['low', 'medium', 'high']);
40
64
  export const TrapStatusSchema = z.enum(['active', 'resolved', 'expired']);
41
- export const PrioritySchema = z.enum(['low', 'medium', 'high']);
65
+ export const PrioritySchema = z.enum(['low', 'medium', 'high', 'critical']);
42
66
  export const MemoryVisibilitySchema = z.enum(['shared', 'machine', 'private']);
43
67
  export const HandoffStatusSchema = z.enum(['open', 'accepted', 'closed']);
68
+ export const ReviewVerdictSchema = z.enum(['approve', 'request_changes']);
44
69
  export const DecisionOutcomeSchema = z.enum(['approved', 'rejected', 'deferred', 'pending']);
45
70
  export const MemoryScopeSchema = z.enum(['project', 'machine', 'user']).default('project');
71
+ /**
72
+ * Typed discriminated-union provenance (Phase 3 slice 3f, P6.3).
73
+ * Tracks how a record entered the store — drives read filters
74
+ * (default excludes `legacy` + low-confidence `auto_reflect`), audit
75
+ * narratives, and federation-safe federation behaviour.
76
+ */
77
+ export const ProvenanceSchema = z.discriminatedUnion('kind', [
78
+ z.object({
79
+ kind: z.literal('agent'),
80
+ agent_id: z.string().optional(),
81
+ session_id: z.string().optional(),
82
+ }),
83
+ z.object({
84
+ kind: z.literal('auto_reflect'),
85
+ source_session: z.string().optional(),
86
+ confidence: z.number().min(0).max(1).optional(),
87
+ }),
88
+ z.object({
89
+ kind: z.literal('user'),
90
+ author: z.string().optional(),
91
+ }),
92
+ z.object({
93
+ kind: z.literal('loop_artifact'),
94
+ loop_id: z.string(),
95
+ slot: z.string().optional(),
96
+ turn: z.number().optional(),
97
+ }),
98
+ z.object({
99
+ kind: z.literal('federation'),
100
+ source_project: z.string(),
101
+ remote_id: z.string().optional(),
102
+ }),
103
+ z.object({
104
+ kind: z.literal('correction'),
105
+ supersedes: z.string(),
106
+ }),
107
+ z.object({
108
+ kind: z.literal('legacy'),
109
+ }),
110
+ ]);
111
+ /**
112
+ * Legacy passthrough kept for backwards compatibility with records
113
+ * that predate slice 3f. Entity shapes carry this (permissive) rather
114
+ * than `ProvenanceSchema.optional()` so that existing files do not
115
+ * fail to parse. New writes go through `stampProvenance()` in
116
+ * entity-operations.ts which enforces the typed shape.
117
+ */
118
+ export const ProvenancePassthroughSchema = z.unknown().optional();
46
119
  export const ConstraintSchema = z.object({
47
120
  schema_version: z.number().int().positive().optional(),
48
121
  id: z.string(),
@@ -58,9 +131,11 @@ export const ConstraintSchema = z.object({
58
131
  status: ConstraintStatusSchema,
59
132
  category: ConstraintCategorySchema.optional(),
60
133
  scope: MemoryScopeSchema.optional(),
61
- tags: z.array(z.string()),
134
+ tags: TagsSchema,
62
135
  related_paths: z.array(z.string()).optional(),
136
+ plan_id: z.string().optional(),
63
137
  expires_at: z.string().optional(),
138
+ provenance: ProvenancePassthroughSchema,
64
139
  });
65
140
  export const DecisionSchema = z.object({
66
141
  schema_version: z.number().int().positive().optional(),
@@ -78,7 +153,8 @@ export const DecisionSchema = z.object({
78
153
  scope: MemoryScopeSchema.optional(),
79
154
  related_paths: z.array(z.string()).optional(),
80
155
  plan_id: z.string().optional(),
81
- tags: z.array(z.string()),
156
+ tags: TagsSchema,
157
+ provenance: ProvenancePassthroughSchema,
82
158
  });
83
159
  export const TrapSchema = z.object({
84
160
  schema_version: z.number().int().positive().optional(),
@@ -94,13 +170,34 @@ export const TrapSchema = z.object({
94
170
  status: TrapStatusSchema.default('active'),
95
171
  severity: SeveritySchema,
96
172
  scope: MemoryScopeSchema.optional(),
97
- tags: z.array(z.string()),
173
+ tags: TagsSchema,
98
174
  related_paths: z.array(z.string()).optional(),
99
175
  plan_id: z.string().optional(),
100
176
  visibility: MemoryVisibilitySchema.default('shared'),
101
177
  host_id: z.string().optional(),
102
178
  expires_at: z.string().optional(),
103
179
  platform_scope: z.string().optional(),
180
+ provenance: ProvenancePassthroughSchema,
181
+ });
182
+ export const HandoffContractSchema = z.object({
183
+ files_touched: z.array(z.string()).optional(),
184
+ pre_conditions: z.array(z.string()).optional(),
185
+ post_conditions: z.array(z.string()).optional(),
186
+ tests_to_verify: z.array(z.string()).optional(),
187
+ linked_plans: z.array(z.string()).optional(),
188
+ });
189
+ export const HandoffReviewSchema = z.object({
190
+ requester: z.string().optional(),
191
+ reviewer: z.string().optional(),
192
+ requested_at: z.string().optional(),
193
+ thread_id: z.string().optional(),
194
+ message_id: z.string().optional(),
195
+ verdict: ReviewVerdictSchema.optional(),
196
+ reviewed_at: z.string().optional(),
197
+ reviewed_by: z.string().optional(),
198
+ summary: z.string().optional(),
199
+ blocking_issues: z.array(z.string()).optional(),
200
+ suggestions: z.array(z.string()).optional(),
104
201
  });
105
202
  export const HandoffSchema = z.object({
106
203
  schema_version: z.number().int().positive().optional(),
@@ -119,11 +216,22 @@ export const HandoffSchema = z.object({
119
216
  status: HandoffStatusSchema,
120
217
  project: z.string().optional(),
121
218
  plan_id: z.string().optional(),
122
- tags: z.array(z.string()),
219
+ narrative: z.string().optional(),
220
+ tags: TagsSchema,
123
221
  related_paths: z.array(z.string()).optional(),
222
+ contract: HandoffContractSchema.optional(),
223
+ review: HandoffReviewSchema.optional(),
124
224
  snapshot: z.object({
125
225
  diff: z.string().optional(),
126
226
  }).optional(),
227
+ provenance: ProvenancePassthroughSchema,
228
+ /**
229
+ * Tombstone pointer (P6.1). Present on correction handoffs that
230
+ * supersede an earlier, incorrect handoff. The original is left
231
+ * immutable; federation and history still carry both.
232
+ */
233
+ superseded_by: z.string().optional(),
234
+ supersedes: z.string().optional(),
127
235
  });
128
236
  export const PlanStatusSchema = z.enum(['todo', 'in_progress', 'blocked', 'done', 'dropped']);
129
237
  export const PlanStepStatusSchema = z.enum(['todo', 'in_progress', 'testing', 'done', 'blocked']);
@@ -150,7 +258,7 @@ export const PlanItemSchema = z.object({
150
258
  priority: PrioritySchema,
151
259
  assignee: z.string().optional(),
152
260
  project: z.string().optional(),
153
- tags: z.array(z.string()),
261
+ tags: TagsSchema,
154
262
  related_paths: z.array(z.string()).optional(),
155
263
  depends_on: z.array(z.string()).default([]),
156
264
  steps: z.array(PlanStepSchema).optional(),
@@ -159,6 +267,36 @@ export const PlanItemSchema = z.object({
159
267
  started_at: z.string().optional(),
160
268
  completed_at: z.string().optional(),
161
269
  });
270
+ export const SequenceStatusSchema = z.enum(['draft', 'active', 'archived']);
271
+ export const SequenceItemSchema = z.object({
272
+ planId: z.string(),
273
+ stepId: z.string().optional(), // Reference a specific step within the plan
274
+ rank: z.number().int().positive(),
275
+ hard_after: z.array(z.string()).default([]),
276
+ soft_after: z.array(z.string()).default([]),
277
+ lane: z.string().optional(),
278
+ scope_hint: z.string().optional(),
279
+ rationale: z.string().optional(),
280
+ });
281
+ export const SequenceSchema = z.object({
282
+ schema_version: z.number().int().positive().optional(),
283
+ id: z.string(),
284
+ short_label: z.string().optional(),
285
+ name: z.string(),
286
+ description: z.string().optional(),
287
+ status: SequenceStatusSchema.default('draft'),
288
+ items: z.array(SequenceItemSchema).default([]),
289
+ owner: z.string().optional(),
290
+ created_at: z.string(),
291
+ updated_at: z.string(),
292
+ author: z.string(),
293
+ author_id: z.string().optional(),
294
+ model: z.string().optional(),
295
+ project_id: z.string().optional(),
296
+ host_id: z.string().optional(),
297
+ session_id: z.string().optional(),
298
+ tags: TagsSchema,
299
+ });
162
300
  export const InstructionLayerSchema = z.enum(['global', 'project', 'agent']);
163
301
  export const InstructionEntrySchema = z.object({
164
302
  schema_version: z.number().int().positive().optional(),
@@ -170,7 +308,7 @@ export const InstructionEntrySchema = z.object({
170
308
  updated_at: z.string(),
171
309
  author: z.string(),
172
310
  model: z.string().optional(),
173
- tags: z.array(z.string()).default([]),
311
+ tags: TagsWithDefaultSchema,
174
312
  active: z.boolean().default(true),
175
313
  supersedes: z.string().optional(),
176
314
  });
@@ -183,7 +321,7 @@ export const ProjectCapabilitySchema = z.object({
183
321
  category: z.string(), // e.g. "auth", "api", "storage", "testing"
184
322
  provided_by: z.string().optional(), // path to implementation
185
323
  requires: z.array(z.string()).optional(), // capability IDs this depends on
186
- tags: z.array(z.string()),
324
+ tags: TagsSchema,
187
325
  example_usage: z.string().optional(),
188
326
  status: CapabilityStatusSchema.default('stable'),
189
327
  related_paths: z.array(z.string()).optional(),
@@ -205,7 +343,7 @@ export const ProjectToolSchema = z.object({
205
343
  requires: z.array(z.string()).optional(), // tool IDs this depends on
206
344
  suggests_for: z.array(z.string()).optional(), // agent types or domains
207
345
  invocation_example: z.string().optional(),
208
- tags: z.array(z.string()),
346
+ tags: TagsSchema,
209
347
  status: CapabilityStatusSchema.default('stable'),
210
348
  related_paths: z.array(z.string()).optional(),
211
349
  created_at: z.string(),
@@ -213,6 +351,52 @@ export const ProjectToolSchema = z.object({
213
351
  author_id: z.string().optional(),
214
352
  model: z.string().optional(),
215
353
  });
354
+ // --- Message schema (inter-agent inbox) ---
355
+ export const MessageTypeSchema = z.enum(['assign', 'review', 'rfc', 'info', 'reply']);
356
+ export const MessageStatusSchema = z.enum(['pending', 'read', 'acknowledged', 'archived']);
357
+ export const InboxMessageSchema = z.object({
358
+ schema_version: z.number().int().positive().optional(),
359
+ id: z.string(),
360
+ short_label: z.string().optional(),
361
+ /** Sender agent name */
362
+ from: z.string(),
363
+ /** Target agent name */
364
+ to: z.string(),
365
+ /** Message type: assign (work), review (feedback request), rfc (ideation), info (notification), reply (response in thread) */
366
+ type: MessageTypeSchema,
367
+ /** Human-readable message body */
368
+ text: z.string(),
369
+ /** Reference to a plan, sequence, handoff, or RFC thread */
370
+ ref: z.string().optional(),
371
+ /** Structured payload — brief, context, criteria, or any structured data */
372
+ payload: z.record(z.string(), z.unknown()).optional(),
373
+ /** File scope relevant to this message */
374
+ scope: z.string().optional(),
375
+ /** Whether the recipient must acknowledge */
376
+ requires_ack: z.boolean().default(false),
377
+ /** Thread ID for multi-turn conversations (RFC ideation, review rounds) */
378
+ thread_id: z.string().optional(),
379
+ /** Status tracking */
380
+ status: MessageStatusSchema.default('pending'),
381
+ /** When the message was read */
382
+ read_at: z.string().optional(),
383
+ /** When the message was acknowledged */
384
+ ack_at: z.string().optional(),
385
+ created_at: z.string(),
386
+ updated_at: z.string(),
387
+ author: z.string(),
388
+ author_id: z.string().optional(),
389
+ model: z.string().optional(),
390
+ project_id: z.string().optional(),
391
+ host_id: z.string().optional(),
392
+ session_id: z.string().optional(),
393
+ /** Top-level claim_id for dispatch routing. Instances filter their inbox by this field.
394
+ * Also present in payload.claim_id for backward compat — this top-level field is authoritative. */
395
+ claim_id: z.string().optional(),
396
+ /** Top-level assignment_id for Agent SDK protocol. Enables filtering/display without parsing payload. */
397
+ assignment_id: z.string().optional(),
398
+ tags: TagsWithDefaultSchema,
399
+ });
216
400
  // --- State schema ---
217
401
  export const StateSchema = z.object({
218
402
  version: z.literal(1),
@@ -228,10 +412,35 @@ export const RedactionConfigSchema = z.object({
228
412
  enabled: z.boolean(),
229
413
  patterns: z.array(z.string()),
230
414
  });
415
+ export const PreinstallThresholdsSchema = z.object({
416
+ composite_pass: z.number().min(0).max(100).default(70),
417
+ composite_warn: z.number().min(0).max(100).default(50),
418
+ supply_chain_block: z.number().min(0).max(100).default(30),
419
+ vulnerability_block: z.number().min(0).max(100).default(20),
420
+ });
421
+ export const PreinstallWeightsSchema = z.object({
422
+ supply_chain: z.number().min(0).max(1).default(0.35),
423
+ vulnerability: z.number().min(0).max(1).default(0.30),
424
+ quality: z.number().min(0).max(1).default(0.15),
425
+ maintenance: z.number().min(0).max(1).default(0.15),
426
+ license: z.number().min(0).max(1).default(0.05),
427
+ });
428
+ export const PreinstallConfigSchema = z.object({
429
+ enabled: z.boolean().default(false),
430
+ mode: z.enum(['advisory', 'enforced']).default('advisory'),
431
+ thresholds: PreinstallThresholdsSchema.prefault({}),
432
+ weights: PreinstallWeightsSchema.prefault({}),
433
+ cache_ttl_hours: z.number().positive().default(24),
434
+ fallback_on_error: z.enum(['warn', 'pass', 'block']).default('warn'),
435
+ allowlist: z.array(z.string()).default([]),
436
+ denylist: z.array(z.string()).default([]),
437
+ socket_endpoint: z.string().default('https://mcp.socket.dev/'),
438
+ });
231
439
  export const SecurityConfigSchema = z.object({
232
440
  mode: z.enum(['warn', 'strict']).default('warn'),
233
441
  strict_redaction: z.boolean().default(false),
234
442
  block_sensitive_paths: z.boolean().default(true),
443
+ preinstall: PreinstallConfigSchema.optional(),
235
444
  });
236
445
  export const MarkdownConfigSchema = z.object({
237
446
  max_items_per_section: z.number().default(20),
@@ -241,6 +450,8 @@ export const MarkdownConfigSchema = z.object({
241
450
  export const CandidateTypeSchema = z.enum([
242
451
  'constraint', 'decision', 'trap', 'handoff',
243
452
  ]);
453
+ /** Who originated this candidate. 'auto' = session-end auto-reflect; 'agent' = intentional agent action; 'human' = human-created or unknown legacy item. */
454
+ export const CandidateSourceSchema = z.enum(['auto', 'agent', 'human']);
244
455
  export const CandidateStatusSchema = z.enum(['pending', 'accepted', 'rejected']);
245
456
  export const CandidateUseSchema = z.object({
246
457
  by: z.string(),
@@ -257,7 +468,28 @@ export const CandidateContradictionSchema = z.object({
257
468
  score: z.number(),
258
469
  kind: z.string(),
259
470
  });
260
- export const CandidateSchema = z.object({
471
+ /** Legacy candidates stored `source` as free-text (e.g. 'session-end:git-diff:sess_xxx',
472
+ * 'runtime-note:agent:id'). Worker 2 narrowed `source` to an enum. To preserve
473
+ * provenance without rewriting files, we migrate free-text values to `origin`
474
+ * on read via this preprocess. Files are NOT rewritten — preprocess only
475
+ * affects parsed in-memory values. */
476
+ const CANDIDATE_SOURCE_ENUM = new Set(['auto', 'agent', 'human']);
477
+ const candidatePreprocess = (raw) => {
478
+ if (!raw || typeof raw !== 'object')
479
+ return raw;
480
+ const obj = raw;
481
+ const src = obj.source;
482
+ if (typeof src === 'string' && !CANDIDATE_SOURCE_ENUM.has(src)) {
483
+ // Free-text source → preserve into origin (if not already set), drop from source.
484
+ const clone = { ...obj };
485
+ if (clone.origin === undefined)
486
+ clone.origin = src;
487
+ clone.source = undefined;
488
+ return clone;
489
+ }
490
+ return raw;
491
+ };
492
+ export const CandidateSchema = z.preprocess(candidatePreprocess, z.object({
261
493
  schema_version: z.number().int().positive().optional(),
262
494
  id: z.string(),
263
495
  short_label: z.string().optional(),
@@ -270,8 +502,15 @@ export const CandidateSchema = z.object({
270
502
  project_id: z.string().optional(),
271
503
  host_id: z.string().optional(),
272
504
  session_id: z.string().optional(),
273
- source: z.string().optional(),
274
- tags: z.array(z.string()),
505
+ /** Normalized category of the originator. Missing field / unknown legacy value
506
+ * falls back to `origin`-based inference, then to 'human'. */
507
+ source: CandidateSourceSchema.optional().catch(undefined),
508
+ /** Free-text provenance string preserved for reputation/audit. Examples:
509
+ * 'session-end:git-diff:sess_xxx', 'runtime-note:<agent>:<note_id>',
510
+ * 'mcp:quick-capture', 'cross-project:<project>'. Used alongside `source`
511
+ * (which is the enum); not narrowed by Zod. */
512
+ origin: z.string().optional(),
513
+ tags: TagsSchema,
275
514
  status: CandidateStatusSchema,
276
515
  // type-specific optional fields
277
516
  severity: SeveritySchema.optional(),
@@ -285,13 +524,15 @@ export const CandidateSchema = z.object({
285
524
  usage_events: z.array(CandidateUseSchema).default([]),
286
525
  last_used_at: z.string().optional(),
287
526
  plan_id: z.string().optional(),
527
+ narrative: z.string().optional(),
288
528
  contradictions_detected: z.array(CandidateContradictionSchema).optional(),
289
529
  contradiction_summary: z.string().optional(),
290
530
  promotion_blocked_reason: z.string().optional(),
291
531
  resolved_at: z.string().optional(),
292
532
  resolved_by: z.string().optional(),
293
533
  resolution_reason: z.string().optional(),
294
- });
534
+ provenance: ProvenancePassthroughSchema,
535
+ }));
295
536
  export const ReflectiveMemoryConfigSchema = z.object({
296
537
  enabled: z.boolean().default(true),
297
538
  auto_accept: z.boolean().default(false),
@@ -319,11 +560,14 @@ export const ReputationConfigSchema = z.object({
319
560
  });
320
561
  // --- Work claims schemas ---
321
562
  export const ClaimStatusSchema = z.enum(['active', 'released', 'stale']);
563
+ export const ClaimHandoffModeSchema = z.enum(['self-commit', 'integrator']);
322
564
  export const ClaimSchema = z.object({
323
565
  schema_version: z.number().int().positive().optional(),
324
566
  id: z.string(),
325
567
  agent: z.string(),
326
568
  agent_id: z.string().optional(),
569
+ /** OS user who created this claim. */
570
+ user: z.string().optional(),
327
571
  project_id: z.string().optional(),
328
572
  host_id: z.string().optional(),
329
573
  session_id: z.string().optional(),
@@ -336,6 +580,178 @@ export const ClaimSchema = z.object({
336
580
  released_at: z.string().optional(),
337
581
  expires_at: z.string().optional(),
338
582
  model: z.string().optional(),
583
+ /** Absolute path to the git worktree associated with this claim, if one was created. */
584
+ worktree_path: z.string().optional(),
585
+ /** Handoff mode: "self-commit" = worker commits+merges, "integrator" = another agent reviews+merges. */
586
+ handoff_mode: ClaimHandoffModeSchema.optional(),
587
+ /** ISO timestamp when a spawned instance adopted this claim via session_start. */
588
+ adopted_at: z.string().optional(),
589
+ /** Message ID of the dispatch assignment that created this claim. For tracing claim→message→instance. */
590
+ assignment_message_id: z.string().optional(),
591
+ /** Assignment ID from the Agent SDK runtime protocol. Links claim to its Assignment lifecycle entity. */
592
+ assignment_id: z.string().optional(),
593
+ });
594
+ // --- Assignment schemas (Agent SDK runtime protocol) ---
595
+ export const AssignmentStatusSchema = z.enum([
596
+ 'created', // Record exists, not yet offered to agent
597
+ 'offered', // Brief delivered to agent inbox
598
+ 'accepted', // Worker acknowledged receipt
599
+ 'started', // Worker reports active work begun
600
+ 'completed', // Worker reports successful completion
601
+ 'failed', // Worker reports failure
602
+ 'blocked', // Worker reports external blocker
603
+ 'timed_out', // Sweeper detected no heartbeat within TTL
604
+ 'expired', // Offered but never accepted within TTL
605
+ 'retrying', // Failed/timed-out assignment being requeued
606
+ 'rerouted', // Blocked assignment rerouted to different agent
607
+ ]);
608
+ export const AssignmentArtifactSchema = z.object({
609
+ type: z.string(),
610
+ ref: z.string(),
611
+ description: z.string().optional(),
612
+ });
613
+ export const AssignmentSchema = z.object({
614
+ schema_version: z.number().int().positive().optional(),
615
+ id: z.string(),
616
+ short_label: z.string().optional(),
617
+ // Cross-references (links, not replacement)
618
+ claim_id: z.string(),
619
+ message_id: z.string().optional(),
620
+ plan_id: z.string().optional(),
621
+ sequence_id: z.string().optional(),
622
+ /** For retry chains: original assignment_id. */
623
+ correlation_id: z.string().optional(),
624
+ // Actors
625
+ agent: z.string(),
626
+ agent_id: z.string().optional(),
627
+ session_id: z.string().optional(),
628
+ dispatcher_agent: z.string(),
629
+ dispatcher_session_id: z.string().optional(),
630
+ // Task metadata
631
+ scope: z.string(),
632
+ description: z.string(),
633
+ lane: z.string().optional(),
634
+ worktree_path: z.string().optional(),
635
+ // Status FSM
636
+ status: AssignmentStatusSchema,
637
+ status_reason: z.string().optional(),
638
+ // Timestamps
639
+ created_at: z.string(),
640
+ updated_at: z.string().optional(),
641
+ offered_at: z.string().optional(),
642
+ accepted_at: z.string().optional(),
643
+ started_at: z.string().optional(),
644
+ completed_at: z.string().optional(),
645
+ failed_at: z.string().optional(),
646
+ blocked_at: z.string().optional(),
647
+ timed_out_at: z.string().optional(),
648
+ expired_at: z.string().optional(),
649
+ rerouted_at: z.string().optional(),
650
+ last_heartbeat_at: z.string().optional(),
651
+ // Result
652
+ artifacts: z.array(AssignmentArtifactSchema).default([]),
653
+ error_message: z.string().optional(),
654
+ retry_count: z.number().int().default(0),
655
+ max_retries: z.number().int().default(2),
656
+ // Timeout config (ms)
657
+ heartbeat_ttl_ms: z.number().int().default(30 * 60_000), // 30 min
658
+ acceptance_ttl_ms: z.number().int().default(15 * 60_000), // 15 min
659
+ tags: TagsWithDefaultSchema,
660
+ });
661
+ // --- AgentRun schemas (execution-layer runtime state) ---
662
+ export const AgentRunTransportSchema = z.enum([
663
+ 'cli_spawn',
664
+ 'manual_command',
665
+ 'inbox_only',
666
+ ]);
667
+ export const AgentRunStatusSchema = z.enum([
668
+ 'created',
669
+ 'launching',
670
+ 'waiting_input',
671
+ 'running',
672
+ 'blocked',
673
+ 'completed',
674
+ 'failed',
675
+ 'cancelled',
676
+ 'timed_out',
677
+ 'interrupted',
678
+ ]);
679
+ export const AgentRunSchema = z.object({
680
+ schema_version: z.number().int().positive().optional(),
681
+ id: z.string(),
682
+ short_label: z.string().optional(),
683
+ assignment_id: z.string(),
684
+ claim_id: z.string(),
685
+ message_id: z.string().optional(),
686
+ plan_id: z.string().optional(),
687
+ sequence_id: z.string().optional(),
688
+ retry_of_run_id: z.string().optional(),
689
+ attempt_index: z.number().int().positive().default(1),
690
+ agent: z.string(),
691
+ agent_id: z.string().optional(),
692
+ session_id: z.string().optional(),
693
+ transport: AgentRunTransportSchema,
694
+ status: AgentRunStatusSchema,
695
+ status_reason: z.string().optional(),
696
+ scope: z.string(),
697
+ description: z.string(),
698
+ worktree_path: z.string().optional(),
699
+ command: z.string().optional(),
700
+ shell: z.string().optional(),
701
+ pid: z.number().int().positive().optional(),
702
+ provider_run_id: z.string().optional(),
703
+ created_at: z.string(),
704
+ updated_at: z.string().optional(),
705
+ launched_at: z.string().optional(),
706
+ started_at: z.string().optional(),
707
+ blocked_at: z.string().optional(),
708
+ completed_at: z.string().optional(),
709
+ failed_at: z.string().optional(),
710
+ cancelled_at: z.string().optional(),
711
+ timed_out_at: z.string().optional(),
712
+ interrupted_at: z.string().optional(),
713
+ last_event_at: z.string().optional(),
714
+ artifacts: z.array(AssignmentArtifactSchema).default([]),
715
+ error_message: z.string().optional(),
716
+ tags: TagsWithDefaultSchema,
717
+ });
718
+ // --- ActionRequired schema (runtime pause/resume) ---
719
+ export const ActionRequiredKindSchema = z.enum(['approval', 'user_input', 'clarification', 'plan_approval']);
720
+ export const ActionRequiredStatusSchema = z.enum(['pending', 'resolved', 'rejected', 'cancelled', 'expired']);
721
+ export const ActionRequiredResponseSchema = z.object({
722
+ outcome: z.enum(['resolved', 'rejected', 'cancelled']),
723
+ text: z.string().optional(),
724
+ payload: z.record(z.string(), z.unknown()).optional(),
725
+ responded_by: z.string(),
726
+ responded_by_id: z.string().optional(),
727
+ responded_at: z.string(),
728
+ });
729
+ export const ActionRequiredSchema = z.object({
730
+ schema_version: z.number().int().positive().optional(),
731
+ id: z.string(),
732
+ short_label: z.string().optional(),
733
+ assignment_id: z.string(),
734
+ run_id: z.string().optional(),
735
+ claim_id: z.string().optional(),
736
+ message_id: z.string().optional(),
737
+ plan_id: z.string().optional(),
738
+ sequence_id: z.string().optional(),
739
+ agent: z.string(),
740
+ agent_id: z.string().optional(),
741
+ session_id: z.string().optional(),
742
+ kind: ActionRequiredKindSchema,
743
+ status: ActionRequiredStatusSchema.default('pending'),
744
+ scope: z.string().optional(),
745
+ title: z.string(),
746
+ prompt: z.string(),
747
+ options: z.array(z.string()).default([]),
748
+ response_schema: z.record(z.string(), z.unknown()).optional(),
749
+ created_at: z.string(),
750
+ updated_at: z.string(),
751
+ expires_at: z.string().optional(),
752
+ resolved_at: z.string().optional(),
753
+ response: ActionRequiredResponseSchema.optional(),
754
+ tags: TagsWithDefaultSchema,
339
755
  });
340
756
  // --- Runtime notes schemas ---
341
757
  export const RuntimeNoteSchema = z.object({
@@ -349,12 +765,13 @@ export const RuntimeNoteSchema = z.object({
349
765
  created_at: z.string(),
350
766
  project: z.string().optional(),
351
767
  plan_id: z.string().optional(),
352
- tags: z.array(z.string()),
768
+ tags: TagsSchema,
353
769
  visibility: MemoryVisibilitySchema.default('shared'),
354
770
  host_id: z.string().optional(),
355
771
  expires_at: z.string().optional(),
356
772
  note_type: z.enum(['observation', 'session_start', 'session_end']).default('observation'),
357
773
  model: z.string().optional(),
774
+ provenance: ProvenancePassthroughSchema,
358
775
  });
359
776
  // --- AI surface task request schemas ---
360
777
  export const AiSurfaceTaskStatusSchema = z.enum(['queued', 'in_progress', 'completed', 'cancelled', 'failed']);
@@ -376,7 +793,7 @@ export const AiSurfaceTaskRequestSchema = z.object({
376
793
  status: AiSurfaceTaskStatusSchema.default('queued'),
377
794
  requested_outputs: z.array(z.string()).default([]),
378
795
  related_paths: z.array(z.string()).optional(),
379
- tags: z.array(z.string()).default([]),
796
+ tags: TagsWithDefaultSchema,
380
797
  claimed_at: z.string().optional(),
381
798
  completed_at: z.string().optional(),
382
799
  result_note: z.string().optional(),
@@ -391,6 +808,30 @@ export const RuntimeEventTypeSchema = z.enum([
391
808
  'task_finished',
392
809
  'session_start',
393
810
  'session_end',
811
+ 'assignment_created',
812
+ 'assignment_offered',
813
+ 'assignment_accepted',
814
+ 'assignment_started',
815
+ 'assignment_progress',
816
+ 'assignment_completed',
817
+ 'assignment_failed',
818
+ 'assignment_blocked',
819
+ 'assignment_timed_out',
820
+ 'assignment_expired',
821
+ 'assignment_retrying',
822
+ 'assignment_rerouted',
823
+ 'run_created',
824
+ 'run_launching',
825
+ 'run_waiting_input',
826
+ 'run_running',
827
+ 'run_blocked',
828
+ 'run_completed',
829
+ 'run_failed',
830
+ 'run_cancelled',
831
+ 'run_timed_out',
832
+ 'run_interrupted',
833
+ 'plan_cascade_to_done',
834
+ 'candidate_harvested',
394
835
  ]);
395
836
  export const RuntimeEventSchema = z.object({
396
837
  id: z.string(),
@@ -402,14 +843,25 @@ export const RuntimeEventSchema = z.object({
402
843
  event_type: RuntimeEventTypeSchema,
403
844
  created_at: z.string(),
404
845
  text: z.string(),
405
- tags: z.array(z.string()).default([]),
846
+ tags: TagsWithDefaultSchema,
847
+ assignment_id: z.string().optional(),
848
+ run_id: z.string().optional(),
849
+ claim_id: z.string().optional(),
850
+ message_id: z.string().optional(),
851
+ plan_id: z.string().optional(),
852
+ sequence_id: z.string().optional(),
853
+ correlation_id: z.string().optional(),
854
+ scope: z.string().optional(),
855
+ transport: z.enum(['cli_spawn', 'manual_command', 'inbox_only']).optional(),
856
+ status: z.string().optional(),
857
+ status_reason: z.string().optional(),
406
858
  // Optional routing and type hints for candidate generation
407
859
  candidate_type: CandidateTypeSchema.optional(),
408
860
  severity: SeveritySchema.optional(),
409
861
  from: z.string().optional(),
410
862
  to: z.string().optional(),
411
863
  related_paths: z.array(z.string()).optional(),
412
- metadata: z.record(z.unknown()).optional(),
864
+ metadata: z.record(z.string(), z.unknown()).optional(),
413
865
  model: z.string().optional(),
414
866
  });
415
867
  // --- Profile schema ---
@@ -435,6 +887,28 @@ export const ProjectIdentityDocumentSchema = z.object({
435
887
  storage_dir: z.string(),
436
888
  topology: TopologyModeSchema,
437
889
  });
890
+ // --- Agent profile schemas ---
891
+ export const AgentProfileTriggerSchema = z.enum(['manual', 'schedule', 'memory_pressure']);
892
+ export const AgentProfileSchema = z.object({
893
+ name: z.string().min(1),
894
+ description: z.string().min(1),
895
+ trust_level: AgentTrustLevelSchema.default('contributor'),
896
+ trigger: AgentProfileTriggerSchema.default('manual'),
897
+ scope: z.string().optional(),
898
+ prompt: z.string().min(1),
899
+ invoke: z.string().min(1),
900
+ tags: TagsWithDefaultSchema,
901
+ });
902
+ export const AgentInvokeSchema = z.object({
903
+ /** CLI command template with {prompt} and {cwd} placeholders */
904
+ command: z.string(),
905
+ /** Delivery channel: spawn (launch CLI process) or inbox (deposit message) */
906
+ channel: z.enum(['spawn', 'inbox']).default('spawn'),
907
+ /** Max execution time in seconds (default: 600 = 10min) */
908
+ timeout: z.number().int().positive().default(600),
909
+ /** Environment variables to set when spawning */
910
+ env: z.record(z.string(), z.string()).optional(),
911
+ }).strict();
438
912
  export const AgentIdentityDocumentSchema = z.object({
439
913
  schema_version: z.number().int().positive().optional(),
440
914
  version: z.literal(1),
@@ -446,6 +920,9 @@ export const AgentIdentityDocumentSchema = z.object({
446
920
  capabilities: z.array(z.string()).default([]),
447
921
  identity_key: AgentIdentityKeySchema.optional(),
448
922
  model: z.string().optional(),
923
+ context_profile: z.enum(['dev', 'dense', 'compact', 'copilot', 'quick', 'openclaw', 'ops', 'research']).optional(),
924
+ /** CLI invoke template for autonomous spawning by coordinator agents */
925
+ invoke: AgentInvokeSchema.optional(),
449
926
  });
450
927
  export const ProjectsConfigSchema = z.object({
451
928
  strategy: ProjectStrategySchema.default('manual'),
@@ -468,6 +945,15 @@ export const SessionSnapshotSchema = z.object({
468
945
  initial_context_hash: z.string().optional(),
469
946
  git_sha: z.string().optional(),
470
947
  });
948
+ export const SessionActiveProjectSchema = z.object({
949
+ /** Absolute path to the project directory. */
950
+ path: z.string(),
951
+ /** Project name from config.yaml (when available). */
952
+ name: z.string().optional(),
953
+ /** ISO timestamp of the switch. */
954
+ switched_at: z.string(),
955
+ }).strict();
956
+ export const IsolationModeSchema = z.enum(['shared-checkout', 'dedicated-worktree']);
471
957
  export const CurrentSessionStateSchema = z.object({
472
958
  schema_version: z.number().int().positive().optional(),
473
959
  session_id: z.string(),
@@ -476,6 +962,20 @@ export const CurrentSessionStateSchema = z.object({
476
962
  agent: z.string(),
477
963
  agent_id: z.string(),
478
964
  host_id: z.string(),
965
+ /** OS user who started this session. */
966
+ user: z.string().optional(),
967
+ /** Process ID of the agent process (for liveness detection). */
968
+ pid: z.number().int().positive().optional(),
969
+ /** LLM model used in this session (e.g. "claude-opus-4-6", "gpt-4.1"). */
970
+ model: z.string().optional(),
971
+ /** Session-scoped active project (overrides global active-project.json). */
972
+ active_project: SessionActiveProjectSchema.optional(),
973
+ /** Git worktree path for this session (undefined = main worktree / shared checkout). */
974
+ worktree_path: z.string().optional(),
975
+ /** Git branch this session is working on. */
976
+ branch: z.string().optional(),
977
+ /** Isolation mode: shared-checkout (default) or dedicated-worktree. */
978
+ isolation_mode: IsolationModeSchema.optional(),
479
979
  });
480
980
  export const MemorySeedKindSchema = z.enum([
481
981
  'command',
@@ -516,7 +1016,7 @@ export const MemorySeedDocumentSchema = z.object({
516
1016
  source_ref: z.string(),
517
1017
  confidence: MemorySeedConfidenceSchema,
518
1018
  related_paths: z.array(z.string()).optional(),
519
- tags: z.array(z.string()).default([]),
1019
+ tags: TagsWithDefaultSchema,
520
1020
  promotion_hint: z.enum(['constraint', 'decision', 'trap']).optional(),
521
1021
  });
522
1022
  export const BootstrapProfileDocumentSchema = z.object({
@@ -547,7 +1047,7 @@ export const BootstrapSuggestionDocumentSchema = z.object({
547
1047
  source_refs: z.array(z.string()).default([]),
548
1048
  layer: z.enum(['global', 'project', 'agent']).optional(),
549
1049
  scope: z.string().optional(),
550
- tags: z.array(z.string()).default([]),
1050
+ tags: TagsWithDefaultSchema,
551
1051
  related_paths: z.array(z.string()).optional(),
552
1052
  category: ConstraintCategorySchema.optional(),
553
1053
  outcome: DecisionOutcomeSchema.optional(),
@@ -581,7 +1081,7 @@ export const BootstrapInterviewAnswerSuggestionSchema = z.object({
581
1081
  confidence: MemorySeedConfidenceSchema.optional(),
582
1082
  layer: z.enum(['global', 'project', 'agent']).optional(),
583
1083
  scope: z.string().optional(),
584
- tags: z.array(z.string()).default([]),
1084
+ tags: TagsWithDefaultSchema,
585
1085
  related_paths: z.array(z.string()).optional(),
586
1086
  category: ConstraintCategorySchema.optional(),
587
1087
  outcome: DecisionOutcomeSchema.optional(),
@@ -637,13 +1137,14 @@ export const AgentIntegrationNameSchema = z.enum([
637
1137
  'antigravity',
638
1138
  'continue',
639
1139
  'roo',
1140
+ 'kilocode',
640
1141
  'openclaw',
641
1142
  'nanoclaw',
642
1143
  'nemoclaw',
643
1144
  'picoclaw',
644
1145
  'zeroclaw',
645
1146
  ]);
646
- export const AgentIntegrationSurfaceKindSchema = z.enum(['instructions', 'mcp', 'skill', 'rule', 'hook']);
1147
+ export const AgentIntegrationSurfaceKindSchema = z.enum(['instructions', 'mcp', 'skill', 'rule', 'hook', 'permissions']);
647
1148
  export const AgentIntegrationLocationSchema = z.enum(['workspace', 'machine']);
648
1149
  export const AgentIntegrationDeclarationSourceSchema = z.enum(['manual', 'detected']);
649
1150
  export const AgentIntegrationSurfaceSchema = z.object({
@@ -666,6 +1167,7 @@ export const CrossProjectLinkSchema = z.object({
666
1167
  path: z.string(),
667
1168
  name: z.string().optional(),
668
1169
  role: z.enum(['subscriber', 'publisher']).default('subscriber'),
1170
+ channels: z.array(z.string()).optional(),
669
1171
  });
670
1172
  export const BrainclawUpdateSourceLocalPackSchema = z.object({
671
1173
  type: z.literal('local-pack'),
@@ -680,6 +1182,20 @@ export const BrainclawUpdateSourceSchema = z.discriminatedUnion('type', [
680
1182
  BrainclawUpdateSourceLocalPackSchema,
681
1183
  BrainclawUpdateSourceNpmSchema,
682
1184
  ]);
1185
+ export const AgentReleaseNotesSchema = z.object({
1186
+ /** One-line summary an agent can surface directly to the operator. */
1187
+ summary: z.string().min(1),
1188
+ /** Concrete impact on agent workflows: new MCP tools, changed behaviour, removed commands. */
1189
+ agent_relevance: z.string().optional(),
1190
+ /** How risky is upgrading without reading the changelog first. */
1191
+ breaking_risk: z.enum(['none', 'low', 'medium', 'high']).default('none'),
1192
+ /** Audience tags ('all', 'multi-agent', 'large-teams'). Absent means 'all'. */
1193
+ recommended_for: z.array(z.string()).optional(),
1194
+ /** Short bullet points the agent can list (max ~5). */
1195
+ highlights: z.array(z.string()).optional(),
1196
+ /** What the agent should tell the operator, e.g. "Safe to auto-install" or "Needs review before upgrading". */
1197
+ action_recommendation: z.string().optional(),
1198
+ });
683
1199
  export const BrainclawLocalReleaseManifestSchema = z.object({
684
1200
  schema_version: z.number().int().positive().optional(),
685
1201
  version: z.literal(1),
@@ -690,6 +1206,7 @@ export const BrainclawLocalReleaseManifestSchema = z.object({
690
1206
  artifact_path: z.string().optional(),
691
1207
  install_command: z.string().optional(),
692
1208
  release_notes: z.string().optional(),
1209
+ agent_release_notes: AgentReleaseNotesSchema.optional(),
693
1210
  });
694
1211
  export const ConfigSchema = z.object({
695
1212
  schema_version: z.number().int().positive().optional(),
@@ -725,5 +1242,13 @@ export const ConfigSchema = z.object({
725
1242
  cross_project_links: z.array(CrossProjectLinkSchema).optional().default([]),
726
1243
  implicit_session_ttl: z.string().default('4h'),
727
1244
  auto_reflect_notes: z.boolean().default(false),
1245
+ auto_refresh_live: z.boolean().default(true),
1246
+ claims: z.object({
1247
+ auto_release_after_hours: z.number().default(24),
1248
+ }).prefault({}),
1249
+ worktree: z.object({
1250
+ shared_paths: z.array(z.string()).default([]),
1251
+ exclude_shared: z.array(z.string()).default([]),
1252
+ }).optional(),
728
1253
  });
729
1254
  //# sourceMappingURL=schema.js.map