brainclaw 1.9.0 → 1.9.1

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 (91) hide show
  1. package/README.md +585 -499
  2. package/dist/brainclaw-vscode.vsix +0 -0
  3. package/dist/commands/harvest.js +1 -1
  4. package/dist/commands/hooks.js +73 -73
  5. package/dist/commands/init.js +1 -1
  6. package/dist/commands/install-hooks.js +78 -78
  7. package/dist/commands/mcp-read-handlers.js +57 -14
  8. package/dist/commands/mcp.js +79 -13
  9. package/dist/commands/switch.js +26 -5
  10. package/dist/commands/version.js +1 -1
  11. package/dist/core/agent-capability.js +19 -4
  12. package/dist/core/agent-files.js +119 -119
  13. package/dist/core/codev-prompts.js +38 -38
  14. package/dist/core/default-profiles/doctor.yaml +11 -11
  15. package/dist/core/default-profiles/janitor.yaml +11 -11
  16. package/dist/core/default-profiles/onboarder.yaml +11 -11
  17. package/dist/core/default-profiles/reviewer.yaml +13 -13
  18. package/dist/core/dispatcher.js +1 -1
  19. package/dist/core/entity-operations.js +29 -3
  20. package/dist/core/execution.js +1 -1
  21. package/dist/core/loops/verbs.js +0 -1
  22. package/dist/core/messaging.js +2 -2
  23. package/dist/core/protocol-skills.js +164 -164
  24. package/dist/core/runtime-signals.js +1 -1
  25. package/dist/core/search.js +19 -2
  26. package/dist/core/security-guard.js +207 -207
  27. package/dist/core/spawn-check.js +16 -2
  28. package/dist/core/staleness.js +1 -1
  29. package/dist/core/store-resolution.js +26 -7
  30. package/dist/core/worktree.js +18 -18
  31. package/dist/facts.js +3 -3
  32. package/dist/facts.json +2 -2
  33. package/docs/PROTOCOL.md +1 -1
  34. package/docs/adapters/openclaw.md +43 -43
  35. package/docs/architecture/project-refs.md +328 -328
  36. package/docs/cli.md +2093 -2093
  37. package/docs/concepts/coordination.md +52 -52
  38. package/docs/concepts/coordinator-runbook.md +129 -129
  39. package/docs/concepts/dispatch-lifecycle.md +245 -245
  40. package/docs/concepts/event-log-store.md +928 -928
  41. package/docs/concepts/ideation-loop.md +317 -317
  42. package/docs/concepts/loop-engine.md +520 -511
  43. package/docs/concepts/mcp-governance.md +268 -268
  44. package/docs/concepts/memory.md +84 -84
  45. package/docs/concepts/multi-agent-workflows.md +167 -167
  46. package/docs/concepts/observer-protocol.md +361 -361
  47. package/docs/concepts/plans-and-claims.md +217 -217
  48. package/docs/concepts/project-md-convention.md +35 -35
  49. package/docs/concepts/runtime-notes.md +38 -38
  50. package/docs/concepts/troubleshooting.md +254 -254
  51. package/docs/concepts/workspace-bootstrapping.md +142 -142
  52. package/docs/context-format-changelog.md +35 -35
  53. package/docs/context-format.md +48 -48
  54. package/docs/index.md +65 -65
  55. package/docs/integrations/agents.md +158 -158
  56. package/docs/integrations/claude-code.md +23 -23
  57. package/docs/integrations/cline.md +77 -77
  58. package/docs/integrations/continue.md +55 -55
  59. package/docs/integrations/copilot.md +68 -68
  60. package/docs/integrations/cursor.md +23 -23
  61. package/docs/integrations/kilocode.md +72 -72
  62. package/docs/integrations/mcp.md +377 -377
  63. package/docs/integrations/mistral-vibe.md +122 -122
  64. package/docs/integrations/openclaw.md +92 -92
  65. package/docs/integrations/opencode.md +84 -84
  66. package/docs/integrations/overview.md +115 -115
  67. package/docs/integrations/roo.md +71 -71
  68. package/docs/integrations/windsurf.md +77 -77
  69. package/docs/mcp-schema-changelog.md +360 -356
  70. package/docs/playbooks/integration/index.md +121 -121
  71. package/docs/playbooks/orchestration.md +37 -0
  72. package/docs/playbooks/productivity/index.md +99 -99
  73. package/docs/playbooks/team/index.md +117 -117
  74. package/docs/product/agent-first-model.md +184 -184
  75. package/docs/product/entity-model-audit.md +462 -462
  76. package/docs/product/positioning.md +86 -86
  77. package/docs/quickstart-existing-project.md +107 -107
  78. package/docs/quickstart.md +183 -183
  79. package/docs/release-maintenance.md +79 -79
  80. package/docs/reputation.md +52 -52
  81. package/docs/review.md +45 -45
  82. package/docs/security.md +212 -212
  83. package/docs/server-operations.md +118 -118
  84. package/docs/storage.md +106 -106
  85. package/package.json +80 -65
  86. package/docs/concepts/event-log-store-critique-A.md +0 -333
  87. package/docs/concepts/event-log-store-critique-B.md +0 -353
  88. package/docs/concepts/event-log-store-phase0-measurements.md +0 -58
  89. package/docs/concepts/event-log-store-proposal-A.md +0 -365
  90. package/docs/concepts/event-log-store-proposal-B.md +0 -404
  91. package/docs/concepts/identity-model-proposal.md +0 -371
@@ -12,18 +12,18 @@ export function truncate(text, maxLength) {
12
12
  * Round 0 — Each agent states their initial position on the topic.
13
13
  */
14
14
  export function buildPositionPrompt(persona, exposition, targetDurationSeconds, responseFilePath) {
15
- return `[CoDev Round 0 — Position initiale]
16
- Tu es ${persona.name}: ${persona.focus}
17
-
18
- ## Sujet
19
- ${truncate(exposition, 800)}
20
-
21
- ## Consigne
22
- Donne ta position en 3-5 phrases maximum. Sois direct et concret.
23
- Durée cible: ${targetDurationSeconds}s.
24
-
25
- ## Format de réponse
26
- Écris ta réponse dans le fichier: ${responseFilePath}
15
+ return `[CoDev Round 0 — Position initiale]
16
+ Tu es ${persona.name}: ${persona.focus}
17
+
18
+ ## Sujet
19
+ ${truncate(exposition, 800)}
20
+
21
+ ## Consigne
22
+ Donne ta position en 3-5 phrases maximum. Sois direct et concret.
23
+ Durée cible: ${targetDurationSeconds}s.
24
+
25
+ ## Format de réponse
26
+ Écris ta réponse dans le fichier: ${responseFilePath}
27
27
  Format: JSON avec { "persona": "${persona.name}", "text": "<ta réponse>" }`;
28
28
  }
29
29
  /**
@@ -34,19 +34,19 @@ export function buildReactionPrompt(persona, previousPositions, roundNumber, tar
34
34
  .filter((p) => p.persona !== persona.name)
35
35
  .map((p) => `**${p.persona}**: ${truncate(p.text, 200)}`)
36
36
  .join('\n');
37
- return `[CoDev Round ${roundNumber} — Réaction]
38
- Tu es ${persona.name}: ${persona.focus}
39
-
40
- ## Positions précédentes
41
- ${positionLines}
42
-
43
- ## Consigne
44
- Réagis aux positions ci-dessus depuis ton point de vue de ${persona.name}.
45
- Challenge, renforce ou propose une alternative. 3-5 phrases.
46
- Durée cible: ${targetDurationSeconds}s.
47
-
48
- ## Format de réponse
49
- Écris ta réponse dans le fichier: ${responseFilePath}
37
+ return `[CoDev Round ${roundNumber} — Réaction]
38
+ Tu es ${persona.name}: ${persona.focus}
39
+
40
+ ## Positions précédentes
41
+ ${positionLines}
42
+
43
+ ## Consigne
44
+ Réagis aux positions ci-dessus depuis ton point de vue de ${persona.name}.
45
+ Challenge, renforce ou propose une alternative. 3-5 phrases.
46
+ Durée cible: ${targetDurationSeconds}s.
47
+
48
+ ## Format de réponse
49
+ Écris ta réponse dans le fichier: ${responseFilePath}
50
50
  Format: JSON avec { "persona": "${persona.name}", "text": "<ta réponse>" }`;
51
51
  }
52
52
  /**
@@ -56,19 +56,19 @@ export function buildConvergencePrompt(persona, allPositions, targetDurationSeco
56
56
  const positionLines = allPositions
57
57
  .map((p) => `[R${p.round}] **${p.persona}**: ${truncate(p.text, 200)}`)
58
58
  .join('\n');
59
- return `[CoDev — Convergence]
60
- Tu es ${persona.name}: ${persona.focus}
61
-
62
- ## Toutes les positions
63
- ${positionLines}
64
-
65
- ## Consigne
66
- Identifie 3 points de convergence et 2 désaccords restants.
67
- Propose des actions concrètes pour avancer. 3-5 phrases.
68
- Durée cible: ${targetDurationSeconds}s.
69
-
70
- ## Format de réponse
71
- Écris ta réponse dans le fichier: ${responseFilePath}
59
+ return `[CoDev — Convergence]
60
+ Tu es ${persona.name}: ${persona.focus}
61
+
62
+ ## Toutes les positions
63
+ ${positionLines}
64
+
65
+ ## Consigne
66
+ Identifie 3 points de convergence et 2 désaccords restants.
67
+ Propose des actions concrètes pour avancer. 3-5 phrases.
68
+ Durée cible: ${targetDurationSeconds}s.
69
+
70
+ ## Format de réponse
71
+ Écris ta réponse dans le fichier: ${responseFilePath}
72
72
  Format: JSON avec { "persona": "${persona.name}", "text": "<ta réponse>" }`;
73
73
  }
74
74
  //# sourceMappingURL=codev-prompts.js.map
@@ -1,11 +1,11 @@
1
- name: doctor
2
- description: Run diagnostics and fix issues automatically
3
- trust_level: trusted
4
- trigger: manual
5
- prompt: >-
6
- Run bclaw_doctor, analyze the findings, and fix what can be fixed
7
- automatically. For issues requiring human judgment, create plans.
8
- invoke: codex exec --full-auto "{prompt}"
9
- tags:
10
- - diagnostics
11
- - built-in
1
+ name: doctor
2
+ description: Run diagnostics and fix issues automatically
3
+ trust_level: trusted
4
+ trigger: manual
5
+ prompt: >-
6
+ Run bclaw_doctor, analyze the findings, and fix what can be fixed
7
+ automatically. For issues requiring human judgment, create plans.
8
+ invoke: codex exec --full-auto "{prompt}"
9
+ tags:
10
+ - diagnostics
11
+ - built-in
@@ -1,11 +1,11 @@
1
- name: janitor
2
- description: Clean up stale claims, archive old notes, check for orphaned files
3
- trust_level: contributor
4
- trigger: manual
5
- prompt: >-
6
- Clean up this project: prune stale claims, archive old runtime notes, check
7
- for orphaned files. Use bclaw_doctor, prune, and release-claims.
8
- invoke: codex exec --full-auto "{prompt}"
9
- tags:
10
- - maintenance
11
- - built-in
1
+ name: janitor
2
+ description: Clean up stale claims, archive old notes, check for orphaned files
3
+ trust_level: contributor
4
+ trigger: manual
5
+ prompt: >-
6
+ Clean up this project: prune stale claims, archive old runtime notes, check
7
+ for orphaned files. Use bclaw_doctor, prune, and release-claims.
8
+ invoke: codex exec --full-auto "{prompt}"
9
+ tags:
10
+ - maintenance
11
+ - built-in
@@ -1,11 +1,11 @@
1
- name: onboarder
2
- description: Generate a project summary for new team members
3
- trust_level: observer
4
- trigger: manual
5
- prompt: >-
6
- Generate a project summary for a new team member. Read the board, plans,
7
- decisions, constraints, and produce a concise onboarding document.
8
- invoke: claude -p "{prompt}" --allowedTools "Edit,Write,Bash,Read,Glob,Grep"
9
- tags:
10
- - onboarding
11
- - built-in
1
+ name: onboarder
2
+ description: Generate a project summary for new team members
3
+ trust_level: observer
4
+ trigger: manual
5
+ prompt: >-
6
+ Generate a project summary for a new team member. Read the board, plans,
7
+ decisions, constraints, and produce a concise onboarding document.
8
+ invoke: claude -p "{prompt}" --allowedTools "Edit,Write,Bash,Read,Glob,Grep"
9
+ tags:
10
+ - onboarding
11
+ - built-in
@@ -1,13 +1,13 @@
1
- name: reviewer
2
- description: Review pending candidates and give structured opinions
3
- trust_level: trusted
4
- trigger: manual
5
- prompt: >-
6
- Review pending candidates in this project. For each, give a structured
7
- opinion (approve/reject with reasons). Use
8
- bclaw_find(entity: "candidate", filter: {status: "pending"}) and
9
- bclaw_transition(entity: "candidate", id, to: "accepted" | "rejected").
10
- invoke: claude -p "{prompt}" --allowedTools "Edit,Write,Bash,Read,Glob,Grep"
11
- tags:
12
- - review
13
- - built-in
1
+ name: reviewer
2
+ description: Review pending candidates and give structured opinions
3
+ trust_level: trusted
4
+ trigger: manual
5
+ prompt: >-
6
+ Review pending candidates in this project. For each, give a structured
7
+ opinion (approve/reject with reasons). Use
8
+ bclaw_find(entity: "candidate", filter: {status: "pending"}) and
9
+ bclaw_transition(entity: "candidate", id, to: "accepted" | "rejected").
10
+ invoke: claude -p "{prompt}" --allowedTools "Edit,Write,Bash,Read,Glob,Grep"
11
+ tags:
12
+ - review
13
+ - built-in
@@ -469,7 +469,7 @@ export function generateBrief(plan, item, cwd, briefMode, options) {
469
469
  if (mode === 'full') {
470
470
  parts.push(buildProtocolSection(options));
471
471
  }
472
- // pln#528 — transport-aware addendum (debrief LeaseUp P1#2). When the agent is
472
+ // pln#528 — transport-aware addendum (field debrief P1#2). When the agent is
473
473
  // spawned sandboxed (no MCP + no git commit — e.g. codex --sandbox
474
474
  // workspace-write), the MCP lifecycle lines in the Protocol section do NOT
475
475
  // apply. Say so explicitly and make the FILE protocol authoritative, so the
@@ -62,6 +62,18 @@ function passesProvenanceFilter(item, filter) {
62
62
  }
63
63
  return true;
64
64
  }
65
+ function isLegacyProvenance(item) {
66
+ return item.provenance?.kind === 'legacy';
67
+ }
68
+ function isLowConfidenceAutoReflect(item, filter) {
69
+ const provenance = item.provenance;
70
+ if (provenance?.kind !== 'auto_reflect')
71
+ return false;
72
+ const threshold = typeof filter.minAutoReflectConfidence === 'number'
73
+ ? filter.minAutoReflectConfidence
74
+ : DEFAULT_MIN_AUTO_REFLECT_CONFIDENCE;
75
+ return (provenance.confidence ?? 0) < threshold;
76
+ }
65
77
  /** Thrown when a verb is not yet wired for a given entity. */
66
78
  export class EntityOperationUnsupportedError extends Error {
67
79
  constructor(entity, verb, hint) {
@@ -129,9 +141,21 @@ function loadAgentRunsWithReconciliation(cwd) {
129
141
  }
130
142
  export function listEntities(name, cwd, filter = {}) {
131
143
  const all = loadAll(name, cwd);
132
- const filtered = applyFilter(all, filter);
144
+ const fieldFiltered = applyFieldFilter(all, filter);
145
+ const excludedLegacy = filter.includeLegacy === true
146
+ ? 0
147
+ : fieldFiltered.filter((item) => isLegacyProvenance(item)).length;
148
+ const excludedLowConfidenceAutoReflect = fieldFiltered.filter((item) => isLowConfidenceAutoReflect(item, filter)).length;
149
+ const filtered = fieldFiltered.filter((item) => passesProvenanceFilter(item, filter));
133
150
  const paged = applyPaging(filtered, filter);
134
- return { entity: name, total: filtered.length, items: paged };
151
+ return {
152
+ entity: name,
153
+ total: filtered.length,
154
+ items: paged,
155
+ excluded_legacy: excludedLegacy,
156
+ excluded_low_confidence_auto_reflect: excludedLowConfidenceAutoReflect,
157
+ total_before_provenance_filter: fieldFiltered.length,
158
+ };
135
159
  }
136
160
  /** Default serialized-items budget (chars) — keeps a bclaw_find payload well under the ~25k-token MCP cap (trp#449). */
137
161
  export const DEFAULT_FIND_CHAR_BUDGET = 40000;
@@ -189,8 +213,10 @@ function loadAll(name, cwd) {
189
213
  }
190
214
  }
191
215
  function applyFilter(items, filter) {
216
+ return applyFieldFilter(items, filter).filter((item) => passesProvenanceFilter(item, filter));
217
+ }
218
+ function applyFieldFilter(items, filter) {
192
219
  let result = items;
193
- result = result.filter((item) => passesProvenanceFilter(item, filter));
194
220
  if (filter.status) {
195
221
  result = result.filter((item) => item.status === filter.status);
196
222
  }
@@ -161,7 +161,7 @@ export async function attemptExecution(invoke, options) {
161
161
  // claim was reused/re-dispatched without one), REFUSE to spawn instead of
162
162
  // falling back to options.cwd — which is the integration repo, where the
163
163
  // worker would edit the main tree directly (dangerous for an autonomous fleet,
164
- // debrief LeaseUp). Return the command for manual, isolated execution.
164
+ // a cross-project field debrief). Return the command for manual, isolated execution.
165
165
  if (options.requireWorktree && !options.worktreePath) {
166
166
  appendAuditEntry({
167
167
  actor: options.dispatcherAgent,
@@ -653,7 +653,6 @@ function assertOpenQuestionsInvariant(thread, intent) {
653
653
  const message = `[brainclaw/loops/fsm] ${intent}: open_questions drift on loop ${thread.id} ` +
654
654
  `— persisted=${JSON.stringify([...persisted])} canonical=${JSON.stringify([...canonical])}`;
655
655
  // Log in prod so drift is visible without taking down the engine.
656
- // eslint-disable-next-line no-console
657
656
  console.warn(message);
658
657
  if (fsmAssertsEnabled()) {
659
658
  throw new Error(message);
@@ -108,7 +108,7 @@ export function readInbox(input, cwd) {
108
108
  if (input.markAsRead) {
109
109
  return mutate({ cwd }, () => {
110
110
  // Fresh read inside lock
111
- let messages = applyInboxFilters(loadMessagesFromDir(dir), input);
111
+ const messages = applyInboxFilters(loadMessagesFromDir(dir), input);
112
112
  const total = messages.length;
113
113
  const offset = input.offset ?? 0;
114
114
  const limit = input.limit ?? 20;
@@ -127,7 +127,7 @@ export function readInbox(input, cwd) {
127
127
  });
128
128
  }
129
129
  // Read-only path: no lock needed
130
- let messages = applyInboxFilters(loadMessagesFromDir(dir), input);
130
+ const messages = applyInboxFilters(loadMessagesFromDir(dir), input);
131
131
  const total = messages.length;
132
132
  const offset = input.offset ?? 0;
133
133
  const limit = input.limit ?? 20;