brainclaw 1.8.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.
- package/README.md +592 -505
- package/dist/brainclaw-vscode.vsix +0 -0
- package/dist/cli.js +138 -13
- package/dist/commands/add-step.js +1 -1
- package/dist/commands/bootstrap.js +2 -26
- package/dist/commands/check-security-mcp.js +50 -33
- package/dist/commands/check-security.js +86 -43
- package/dist/commands/claim.js +22 -21
- package/dist/commands/confirm.js +26 -0
- package/dist/commands/context-diff.js +1 -1
- package/dist/commands/dispatch-watch.js +142 -0
- package/dist/commands/doctor.js +113 -2
- package/dist/commands/estimation-report.js +115 -16
- package/dist/commands/harvest.js +286 -23
- package/dist/commands/hooks.js +73 -73
- package/dist/commands/init.js +124 -22
- package/dist/commands/install-hooks.js +78 -78
- package/dist/commands/loops-handlers.js +4 -0
- package/dist/commands/mcp-read-handlers.js +253 -41
- package/dist/commands/mcp.js +664 -102
- package/dist/commands/memory.js +21 -17
- package/dist/commands/migrate.js +81 -17
- package/dist/commands/prune.js +78 -4
- package/dist/commands/reflect.js +26 -20
- package/dist/commands/register-agent.js +57 -1
- package/dist/commands/repair.js +20 -0
- package/dist/commands/session-end.js +15 -6
- package/dist/commands/session-start.js +18 -1
- package/dist/commands/setup-security.js +39 -18
- package/dist/commands/setup.js +26 -27
- package/dist/commands/stale.js +16 -2
- package/dist/commands/switch.js +26 -5
- package/dist/commands/uninstall.js +126 -34
- package/dist/commands/update-step.js +6 -0
- package/dist/commands/version.js +1 -1
- package/dist/commands/worktree.js +60 -0
- package/dist/core/actions.js +12 -3
- package/dist/core/agent-capability.js +30 -17
- package/dist/core/agent-files.js +963 -666
- package/dist/core/agent-integrations.js +0 -3
- package/dist/core/agent-inventory.js +67 -0
- package/dist/core/agent-registry.js +163 -29
- package/dist/core/agentrun-reconciler.js +33 -2
- package/dist/core/agentruns.js +7 -1
- package/dist/core/ai-agent-detection.js +31 -44
- package/dist/core/archival.js +15 -9
- package/dist/core/assignment-reconciler.js +56 -0
- package/dist/core/assignment-sweeper.js +127 -4
- package/dist/core/assignments.js +69 -11
- package/dist/core/bootstrap.js +233 -67
- package/dist/core/brainclaw-version.js +22 -0
- package/dist/core/candidates.js +21 -1
- package/dist/core/claims.js +313 -150
- package/dist/core/codev-prompts.js +38 -38
- package/dist/core/config.js +6 -1
- package/dist/core/context-diff.js +148 -20
- package/dist/core/context.js +129 -8
- package/dist/core/coordination.js +22 -3
- package/dist/core/default-profiles/doctor.yaml +11 -11
- package/dist/core/default-profiles/janitor.yaml +11 -11
- package/dist/core/default-profiles/onboarder.yaml +11 -11
- package/dist/core/default-profiles/reviewer.yaml +13 -13
- package/dist/core/dispatch-status.js +79 -5
- package/dist/core/dispatcher.js +65 -12
- package/dist/core/entity-operations.js +74 -27
- package/dist/core/entity-registry.js +31 -5
- package/dist/core/event-log.js +138 -21
- package/dist/core/events/checkpoint.js +258 -0
- package/dist/core/events/genesis.js +220 -0
- package/dist/core/events/journal.js +507 -0
- package/dist/core/events/materialize.js +126 -0
- package/dist/core/events/registry-post-image.js +110 -0
- package/dist/core/events/verify.js +109 -0
- package/dist/core/execution-adapters.js +23 -0
- package/dist/core/execution.js +1 -1
- package/dist/core/facade-schema.js +38 -0
- package/dist/core/gc-semantic.js +130 -5
- package/dist/core/handoff-snapshot.js +68 -0
- package/dist/core/ids.js +19 -8
- package/dist/core/instruction-templates.js +34 -115
- package/dist/core/io.js +39 -3
- package/dist/core/json-store.js +10 -1
- package/dist/core/lock.js +153 -28
- package/dist/core/loops/bootstrap-acquire.js +25 -1
- package/dist/core/loops/facade-schema.js +2 -0
- package/dist/core/loops/hooks/survey-signals-baseline.js +36 -0
- package/dist/core/loops/index.js +1 -0
- package/dist/core/loops/presets/bootstrap.js +7 -0
- package/dist/core/loops/store.js +17 -0
- package/dist/core/loops/verbs.js +24 -2
- package/dist/core/markdown.js +8 -76
- package/dist/core/mcp-command-resolution.js +245 -0
- package/dist/core/memory-compactor.js +5 -3
- package/dist/core/memory-lifecycle.js +282 -0
- package/dist/core/merge-risk.js +150 -0
- package/dist/core/messaging.js +10 -3
- package/dist/core/migration.js +11 -1
- package/dist/core/observer-mode.js +26 -0
- package/dist/core/operations/memory-mutation.js +90 -65
- package/dist/core/operations/plan.js +27 -1
- package/dist/core/protocol-skills.js +210 -0
- package/dist/core/reflection-safety.js +6 -7
- package/dist/core/reputation.js +84 -2
- package/dist/core/runtime-signals.js +72 -10
- package/dist/core/runtime.js +84 -1
- package/dist/core/schema.js +114 -0
- package/dist/core/search.js +19 -2
- package/dist/core/security-detectors.js +125 -0
- package/dist/core/security-extract.js +189 -0
- package/dist/core/security-guard.js +217 -139
- package/dist/core/security-packages.js +121 -0
- package/dist/core/security-scoring.js +76 -9
- package/dist/core/security.js +34 -2
- package/dist/core/sequence.js +11 -2
- package/dist/core/setup-flow.js +141 -13
- package/dist/core/spawn-check.js +16 -2
- package/dist/core/staleness.js +73 -2
- package/dist/core/state.js +250 -54
- package/dist/core/store-resolution.js +45 -12
- package/dist/core/worktree.js +90 -26
- package/dist/facts.js +8 -8
- package/dist/facts.json +7 -7
- package/docs/PROTOCOL.md +223 -0
- package/docs/adapters/openclaw.md +43 -43
- package/docs/architecture/project-refs.md +328 -328
- package/docs/cli.md +2097 -2096
- package/docs/concepts/coordination.md +52 -52
- package/docs/concepts/coordinator-runbook.md +129 -0
- package/docs/concepts/dispatch-lifecycle.md +245 -245
- package/docs/concepts/event-log-store.md +928 -0
- package/docs/concepts/ideation-loop.md +317 -317
- package/docs/concepts/loop-engine.md +520 -511
- package/docs/concepts/mcp-governance.md +268 -268
- package/docs/concepts/memory.md +89 -88
- package/docs/concepts/multi-agent-workflows.md +167 -167
- package/docs/concepts/observer-protocol.md +361 -0
- package/docs/concepts/parallel-merge-protocol.md +71 -0
- package/docs/concepts/plans-and-claims.md +217 -174
- package/docs/concepts/project-md-convention.md +35 -35
- package/docs/concepts/runtime-notes.md +38 -38
- package/docs/concepts/skills.md +78 -0
- package/docs/concepts/troubleshooting.md +254 -254
- package/docs/concepts/workspace-bootstrapping.md +142 -81
- package/docs/context-format-changelog.md +35 -35
- package/docs/context-format.md +48 -48
- package/docs/index.md +65 -65
- package/docs/integrations/agents.md +162 -162
- package/docs/integrations/claude-code.md +23 -23
- package/docs/integrations/cline.md +87 -88
- package/docs/integrations/codex.md +2 -2
- package/docs/integrations/continue.md +60 -60
- package/docs/integrations/copilot.md +82 -80
- package/docs/integrations/cursor.md +23 -23
- package/docs/integrations/kilocode.md +72 -72
- package/docs/integrations/mcp.md +377 -377
- package/docs/integrations/mistral-vibe.md +122 -122
- package/docs/integrations/openclaw.md +99 -98
- package/docs/integrations/opencode.md +84 -84
- package/docs/integrations/overview.md +122 -122
- package/docs/integrations/roo.md +74 -74
- package/docs/integrations/windsurf.md +83 -83
- package/docs/mcp-schema-changelog.md +360 -329
- package/docs/playbooks/integration/index.md +121 -121
- package/docs/playbooks/orchestration.md +37 -0
- package/docs/playbooks/productivity/index.md +99 -99
- package/docs/playbooks/team/index.md +117 -117
- package/docs/product/agent-first-model.md +184 -184
- package/docs/product/entity-model-audit.md +462 -462
- package/docs/product/positioning.md +86 -86
- package/docs/quickstart-existing-project.md +107 -107
- package/docs/quickstart.md +148 -147
- package/docs/release-maintenance.md +79 -79
- package/docs/reputation.md +52 -52
- package/docs/review.md +45 -45
- package/docs/security.md +212 -53
- package/docs/server-operations.md +118 -118
- package/docs/storage.md +110 -108
- package/package.json +86 -69
package/dist/commands/hooks.js
CHANGED
|
@@ -9,33 +9,33 @@ import { BRAINCLAW_SECTION_START, BRAINCLAW_SECTION_END, upsertBrainclawSection,
|
|
|
9
9
|
* deterministically into every agent conversation.
|
|
10
10
|
*/
|
|
11
11
|
export function generateCursorHook(projectName) {
|
|
12
|
-
return `---
|
|
13
|
-
description: brainclaw session bootstrap for ${projectName}
|
|
14
|
-
alwaysApply: true
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
# Brainclaw session bootstrap
|
|
18
|
-
|
|
19
|
-
Brainclaw is the shared coordination layer for this project. Use its MCP facades first — the CLI is only a fallback when MCP is unavailable.
|
|
20
|
-
|
|
21
|
-
## At the start of every session
|
|
22
|
-
|
|
23
|
-
Call \`bclaw_work(intent)\` — it handles session setup, context load, and scope claim in a single call.
|
|
24
|
-
|
|
25
|
-
- \`bclaw_work(intent: "resume")\` when continuing an existing task.
|
|
26
|
-
- \`bclaw_work(intent: "execute", scope: "<path>", task: "<text>")\` when starting new work on a specific scope.
|
|
27
|
-
- \`bclaw_work(intent: "consult")\` to read context without claiming.
|
|
28
|
-
|
|
29
|
-
## To coordinate with other agents
|
|
30
|
-
|
|
31
|
-
\`bclaw_coordinate(intent)\` — \`assign\`, \`consult\`, \`review\`, or \`reroute\`.
|
|
32
|
-
|
|
33
|
-
## Before finishing
|
|
34
|
-
|
|
35
|
-
- Release your claims: \`bclaw_release_claim(id)\`.
|
|
36
|
-
- Close out the session: \`bclaw_session_end\` (or let it auto-release via the session hook).
|
|
37
|
-
|
|
38
|
-
CLI fallback only: \`brainclaw context\` / \`brainclaw session-end --auto-release\` if MCP is not reachable.
|
|
12
|
+
return `---
|
|
13
|
+
description: brainclaw session bootstrap for ${projectName}
|
|
14
|
+
alwaysApply: true
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# Brainclaw session bootstrap
|
|
18
|
+
|
|
19
|
+
Brainclaw is the shared coordination layer for this project. Use its MCP facades first — the CLI is only a fallback when MCP is unavailable.
|
|
20
|
+
|
|
21
|
+
## At the start of every session
|
|
22
|
+
|
|
23
|
+
Call \`bclaw_work(intent)\` — it handles session setup, context load, and scope claim in a single call.
|
|
24
|
+
|
|
25
|
+
- \`bclaw_work(intent: "resume")\` when continuing an existing task.
|
|
26
|
+
- \`bclaw_work(intent: "execute", scope: "<path>", task: "<text>")\` when starting new work on a specific scope.
|
|
27
|
+
- \`bclaw_work(intent: "consult")\` to read context without claiming.
|
|
28
|
+
|
|
29
|
+
## To coordinate with other agents
|
|
30
|
+
|
|
31
|
+
\`bclaw_coordinate(intent)\` — \`assign\`, \`consult\`, \`review\`, or \`reroute\`.
|
|
32
|
+
|
|
33
|
+
## Before finishing
|
|
34
|
+
|
|
35
|
+
- Release your claims: \`bclaw_release_claim(id)\`.
|
|
36
|
+
- Close out the session: \`bclaw_session_end\` (or let it auto-release via the session hook).
|
|
37
|
+
|
|
38
|
+
CLI fallback only: \`brainclaw context\` / \`brainclaw session-end --auto-release\` if MCP is not reachable.
|
|
39
39
|
`;
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
@@ -44,58 +44,58 @@ CLI fallback only: \`brainclaw context\` / \`brainclaw session-end --auto-releas
|
|
|
44
44
|
* delimited "SESSION START" block acts as a deterministic trigger.
|
|
45
45
|
*/
|
|
46
46
|
export function generateWindsurfHook(projectName) {
|
|
47
|
-
return `# Brainclaw session trigger — ${projectName}
|
|
48
|
-
# This block is always active. Windsurf Cascade reads .windsurfrules on every activation.
|
|
49
|
-
|
|
50
|
-
## SESSION START (always run first)
|
|
51
|
-
|
|
52
|
-
Call the Brainclaw MCP facade before responding to any request:
|
|
53
|
-
|
|
54
|
-
- \`bclaw_work(intent: "resume")\` when continuing an existing task.
|
|
55
|
-
- \`bclaw_work(intent: "execute", scope: "<path>", task: "<text>")\` when starting new work on a specific scope.
|
|
56
|
-
- \`bclaw_work(intent: "consult")\` to read context without claiming.
|
|
57
|
-
|
|
58
|
-
This returns active constraints, recent decisions, known traps, open plans, active claims, and the last handoff. Do not skip.
|
|
59
|
-
|
|
60
|
-
## COORDINATION
|
|
61
|
-
|
|
62
|
-
\`bclaw_coordinate(intent)\` to assign, consult, review, or reroute other agents.
|
|
63
|
-
|
|
64
|
-
## SESSION END (before finishing)
|
|
65
|
-
|
|
66
|
-
- \`bclaw_release_claim(id)\` for each claim you hold.
|
|
67
|
-
- \`bclaw_session_end\` to close the session (auto-releases remaining claims).
|
|
68
|
-
|
|
69
|
-
CLI fallback only when MCP is unavailable: \`brainclaw context\` / \`brainclaw session-end --auto-release\`.
|
|
47
|
+
return `# Brainclaw session trigger — ${projectName}
|
|
48
|
+
# This block is always active. Windsurf Cascade reads .windsurfrules on every activation.
|
|
49
|
+
|
|
50
|
+
## SESSION START (always run first)
|
|
51
|
+
|
|
52
|
+
Call the Brainclaw MCP facade before responding to any request:
|
|
53
|
+
|
|
54
|
+
- \`bclaw_work(intent: "resume")\` when continuing an existing task.
|
|
55
|
+
- \`bclaw_work(intent: "execute", scope: "<path>", task: "<text>")\` when starting new work on a specific scope.
|
|
56
|
+
- \`bclaw_work(intent: "consult")\` to read context without claiming.
|
|
57
|
+
|
|
58
|
+
This returns active constraints, recent decisions, known traps, open plans, active claims, and the last handoff. Do not skip.
|
|
59
|
+
|
|
60
|
+
## COORDINATION
|
|
61
|
+
|
|
62
|
+
\`bclaw_coordinate(intent)\` to assign, consult, review, or reroute other agents.
|
|
63
|
+
|
|
64
|
+
## SESSION END (before finishing)
|
|
65
|
+
|
|
66
|
+
- \`bclaw_release_claim(id)\` for each claim you hold.
|
|
67
|
+
- \`bclaw_session_end\` to close the session (auto-releases remaining claims).
|
|
68
|
+
|
|
69
|
+
CLI fallback only when MCP is unavailable: \`brainclaw context\` / \`brainclaw session-end --auto-release\`.
|
|
70
70
|
`;
|
|
71
71
|
}
|
|
72
72
|
/**
|
|
73
73
|
* Generate a generic markdown session-trigger section.
|
|
74
74
|
*/
|
|
75
75
|
export function generateMarkdownHook(agentName, projectName) {
|
|
76
|
-
return `# Brainclaw session trigger — ${projectName}
|
|
77
|
-
# This block is always active. ${agentName} reads this file on every activation.
|
|
78
|
-
|
|
79
|
-
## SESSION START (always run first)
|
|
80
|
-
|
|
81
|
-
Call the Brainclaw MCP facade before responding to any request:
|
|
82
|
-
|
|
83
|
-
- \`bclaw_work(intent: "resume")\` when continuing an existing task.
|
|
84
|
-
- \`bclaw_work(intent: "execute", scope: "<path>", task: "<text>")\` when starting new work on a specific scope.
|
|
85
|
-
- \`bclaw_work(intent: "consult")\` to read context without claiming.
|
|
86
|
-
|
|
87
|
-
This returns active constraints, recent decisions, known traps, open plans, active claims, and the last handoff. Do not skip.
|
|
88
|
-
|
|
89
|
-
## COORDINATION
|
|
90
|
-
|
|
91
|
-
\`bclaw_coordinate(intent)\` to assign, consult, review, or reroute other agents.
|
|
92
|
-
|
|
93
|
-
## SESSION END (before finishing)
|
|
94
|
-
|
|
95
|
-
- \`bclaw_release_claim(id)\` for each claim you hold.
|
|
96
|
-
- \`bclaw_session_end\` to close the session (auto-releases remaining claims).
|
|
97
|
-
|
|
98
|
-
CLI fallback only when MCP is unavailable: \`brainclaw context\` / \`brainclaw session-end --auto-release\`.
|
|
76
|
+
return `# Brainclaw session trigger — ${projectName}
|
|
77
|
+
# This block is always active. ${agentName} reads this file on every activation.
|
|
78
|
+
|
|
79
|
+
## SESSION START (always run first)
|
|
80
|
+
|
|
81
|
+
Call the Brainclaw MCP facade before responding to any request:
|
|
82
|
+
|
|
83
|
+
- \`bclaw_work(intent: "resume")\` when continuing an existing task.
|
|
84
|
+
- \`bclaw_work(intent: "execute", scope: "<path>", task: "<text>")\` when starting new work on a specific scope.
|
|
85
|
+
- \`bclaw_work(intent: "consult")\` to read context without claiming.
|
|
86
|
+
|
|
87
|
+
This returns active constraints, recent decisions, known traps, open plans, active claims, and the last handoff. Do not skip.
|
|
88
|
+
|
|
89
|
+
## COORDINATION
|
|
90
|
+
|
|
91
|
+
\`bclaw_coordinate(intent)\` to assign, consult, review, or reroute other agents.
|
|
92
|
+
|
|
93
|
+
## SESSION END (before finishing)
|
|
94
|
+
|
|
95
|
+
- \`bclaw_release_claim(id)\` for each claim you hold.
|
|
96
|
+
- \`bclaw_session_end\` to close the session (auto-releases remaining claims).
|
|
97
|
+
|
|
98
|
+
CLI fallback only when MCP is unavailable: \`brainclaw context\` / \`brainclaw session-end --auto-release\`.
|
|
99
99
|
`;
|
|
100
100
|
}
|
|
101
101
|
export function writeHook(content, relativePath, cwd) {
|
package/dist/commands/init.js
CHANGED
|
@@ -16,8 +16,11 @@ import { BRAINCLAW_EXCLUSIVE_DIRECTORIES, describeAutoConfigWrite, ensureAgentFi
|
|
|
16
16
|
import { detectAiAgent, detectWslEnvironment } from '../core/ai-agent-detection.js';
|
|
17
17
|
import { buildAiSurfaceInventory, renderAiSurfaceUsageHints } from '../core/ai-surface-inventory.js';
|
|
18
18
|
import { ensureUserStore, hasCompletedSetup } from '../core/setup-state.js';
|
|
19
|
+
import { resolveEmptyMemoryRecommendation } from '../core/setup-flow.js';
|
|
19
20
|
import { writeDetectedAgentExport } from './export.js';
|
|
20
21
|
import { writeDetectedAgentHooks } from './hooks.js';
|
|
22
|
+
import { checkGitPresence, runGlobalInstall } from './setup.js';
|
|
23
|
+
import { createBackup, BackupError } from '../core/upgrades/backup.js';
|
|
21
24
|
import { ConfigSchema } from '../core/schema.js';
|
|
22
25
|
export async function runInit(options = {}) {
|
|
23
26
|
const cwd = options.cwd ?? process.cwd();
|
|
@@ -29,6 +32,14 @@ export async function runInit(options = {}) {
|
|
|
29
32
|
if (!hasCompletedSetup()) {
|
|
30
33
|
ensureUserStore();
|
|
31
34
|
}
|
|
35
|
+
// Git-presence gate, aligned with `brainclaw setup`: agent-first onboarding
|
|
36
|
+
// assumes git for memory versioning + post-merge hooks. Allow override via
|
|
37
|
+
// BRAINCLAW_SKIP_REPO_ANALYSIS=1 for tests that exercise non-git fixtures.
|
|
38
|
+
if (process.env.BRAINCLAW_SKIP_REPO_ANALYSIS !== '1' && !checkGitPresence()) {
|
|
39
|
+
console.error('brainclaw init needs git to work.');
|
|
40
|
+
console.error('Install git from https://git-scm.com and try again.');
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
32
43
|
if (containingMemoryStore) {
|
|
33
44
|
console.error(`Error: cannot run \`brainclaw init\` from inside an existing project memory store (${containingMemoryStore}).`);
|
|
34
45
|
console.error('Run `brainclaw init` from the project root directory instead.');
|
|
@@ -61,6 +72,29 @@ export async function runInit(options = {}) {
|
|
|
61
72
|
const storageDir = resolveStorageDir(options.storageDir);
|
|
62
73
|
const projectMemoryExists = memoryExists(cwd);
|
|
63
74
|
const existingConfig = projectMemoryExists ? loadExistingConfig(cwd, storageDir) : undefined;
|
|
75
|
+
// --force backup gate: feedback_no_init_force (June 2026) entered the code.
|
|
76
|
+
// Before rebuilding identity fields on top of an existing store, take a
|
|
77
|
+
// sibling backup so curator personalisations (redaction patterns, claim
|
|
78
|
+
// TTL, governance, sensitive_paths) can always be recovered even if the
|
|
79
|
+
// merge below regresses or the agent ran `init --force` by mistake.
|
|
80
|
+
let forceBackupPath;
|
|
81
|
+
if (options.force && projectMemoryExists) {
|
|
82
|
+
try {
|
|
83
|
+
const handle = createBackup({
|
|
84
|
+
storePath: path.join(cwd, storageDir),
|
|
85
|
+
note: 'init --force pre-reconstruction snapshot',
|
|
86
|
+
storeSchemaVersion: existingConfig ? String(existingConfig.schema_version) : null,
|
|
87
|
+
});
|
|
88
|
+
forceBackupPath = handle.backupPath;
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
const reason = err instanceof BackupError
|
|
92
|
+
? `${err.code}: ${err.message}`
|
|
93
|
+
: err instanceof Error ? err.message : String(err);
|
|
94
|
+
console.error(`Error: --force backup failed (${reason}). Aborting to preserve the existing store. Re-run without --force, or move the store aside manually.`);
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
64
98
|
const topology = resolveTopology(options.topology, existingConfig?.topology);
|
|
65
99
|
const ignoreStrategy = resolveIgnoreStrategy(topology, existingConfig?.ignore_strategy);
|
|
66
100
|
const skipAgentBootstrap = options.skipAgentBootstrap === true || process.env.BRAINCLAW_SKIP_AGENT_BOOTSTRAP === '1';
|
|
@@ -83,11 +117,13 @@ export async function runInit(options = {}) {
|
|
|
83
117
|
});
|
|
84
118
|
// Auto-detect and register the AI coding agent running in this environment
|
|
85
119
|
const detectedAi = skipAgentBootstrap ? undefined : detectAiAgent();
|
|
86
|
-
|
|
120
|
+
const registeredAiAgent = detectedAi
|
|
87
121
|
? registerAgentIdentity({
|
|
88
122
|
agentName: detectedAi.name,
|
|
89
123
|
kind: detectedAi.kind,
|
|
90
|
-
|
|
124
|
+
// pln#562 step 2 — auto-registration never exceeds contributor;
|
|
125
|
+
// elevation is an explicit curator act (set-trust / register-agent).
|
|
126
|
+
trustLevel: 'contributor',
|
|
91
127
|
cwd,
|
|
92
128
|
preferredDirName: storageDir,
|
|
93
129
|
})
|
|
@@ -123,7 +159,15 @@ export async function runInit(options = {}) {
|
|
|
123
159
|
storageDir,
|
|
124
160
|
topology,
|
|
125
161
|
ignoreStrategy,
|
|
126
|
-
|
|
162
|
+
// --force rebuilds identity (project_id, agent, topology, storage_dir)
|
|
163
|
+
// but merges through existingConfig so curator personalisations
|
|
164
|
+
// (redaction patterns, governance, claims TTL, sensitive_paths,
|
|
165
|
+
// cross_project_links, custom markdown caps) survive the reset.
|
|
166
|
+
// The original `force ? undefined` path wiped these silently —
|
|
167
|
+
// discovered when feedback_no_init_force was promoted from a memory
|
|
168
|
+
// habit to a tracked regression.
|
|
169
|
+
existingConfig,
|
|
170
|
+
defaultJournalMode: !projectMemoryExists,
|
|
127
171
|
compact: options.compact === true,
|
|
128
172
|
});
|
|
129
173
|
if (detectedAi && isAgentIntegrationName(detectedAi.name)) {
|
|
@@ -141,6 +185,19 @@ export async function runInit(options = {}) {
|
|
|
141
185
|
.filter((hook) => hook.relativePath !== detectedExport?.relativePath))
|
|
142
186
|
: [];
|
|
143
187
|
const detectedAutoConfig = detectedAi ? writeDetectedAgentAutoConfig(detectedAi.name, cwd) : [];
|
|
188
|
+
// Per-agent slice of machine prerequisites (the same writes setup performs
|
|
189
|
+
// globally, but scoped to the detected agent). This makes `init` the single
|
|
190
|
+
// entry point for the carte-blanche / fresh-repo case: an agent-first
|
|
191
|
+
// bootstrap no longer needs a separate `brainclaw setup` shell-out + session
|
|
192
|
+
// reload. Idempotent — each ensure* function returns "skipped" when the
|
|
193
|
+
// agent's user-scope config doesn't exist.
|
|
194
|
+
const skipMachinePrereqs = options.skipMachinePrereqs === true
|
|
195
|
+
|| skipAgentBootstrap
|
|
196
|
+
|| testMode
|
|
197
|
+
|| process.env.BRAINCLAW_INIT_SKIP_MACHINE_PREREQS === '1';
|
|
198
|
+
const machinePrereqsWritten = detectedAi && !skipMachinePrereqs
|
|
199
|
+
? safeRunMachinePrereqs(detectedAi.name)
|
|
200
|
+
: [];
|
|
144
201
|
// Register in global project registry
|
|
145
202
|
try {
|
|
146
203
|
const entry = scanProject(cwd);
|
|
@@ -177,7 +234,10 @@ export async function runInit(options = {}) {
|
|
|
177
234
|
if (projectMemoryExists) {
|
|
178
235
|
console.log(`✔ Refreshed existing project memory in ${storageDir}/`);
|
|
179
236
|
if (options.force) {
|
|
180
|
-
|
|
237
|
+
if (forceBackupPath) {
|
|
238
|
+
console.log(`✔ Pre-reconstruction backup at ${forceBackupPath} (rollback: brainclaw upgrade --rollback)`);
|
|
239
|
+
}
|
|
240
|
+
console.log('✔ Existing memory preserved; rebuilt managed identity and refreshed agent integration files (customisations merged through)');
|
|
181
241
|
}
|
|
182
242
|
else {
|
|
183
243
|
console.log('✔ Existing memory preserved; refreshed managed configuration and agent integration files');
|
|
@@ -192,6 +252,12 @@ export async function runInit(options = {}) {
|
|
|
192
252
|
if (registeredAiAgent) {
|
|
193
253
|
console.log(`✔ AI agent detected: ${registeredAiAgent.agent_name} [${detectedAi.detection_source}] (${registeredAiAgent.agent_id})`);
|
|
194
254
|
}
|
|
255
|
+
if (machinePrereqsWritten.length > 0) {
|
|
256
|
+
console.log(`\u2714 Machine prerequisites for ${detectedAi.name}:`);
|
|
257
|
+
for (const filePath of machinePrereqsWritten) {
|
|
258
|
+
console.log(` - ${filePath}`);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
195
261
|
if (detectedExport) {
|
|
196
262
|
console.log(`\u2714 Agent instructions written to ${detectedExport.relativePath} (${detectedExport.created ? 'created' : 'updated'})`);
|
|
197
263
|
}
|
|
@@ -265,25 +331,36 @@ export async function runInit(options = {}) {
|
|
|
265
331
|
// Install post-merge hook for auto-release of claims after merge
|
|
266
332
|
installPostMergeHookIfMissing(cwd);
|
|
267
333
|
if (!testMode) {
|
|
268
|
-
|
|
334
|
+
// Shared empty-memory rule (see docs/concepts/workspace-bootstrapping.md):
|
|
335
|
+
// repo with content → bclaw_bootstrap extraction; greenfield → bootstrap
|
|
336
|
+
// loop. The brownfield preflight scan is skipped on greenfield — there is
|
|
337
|
+
// nothing to harvest yet.
|
|
338
|
+
const emptyMemoryRec = resolveEmptyMemoryRecommendation(cwd);
|
|
269
339
|
console.log('');
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
console.log(` ${line}`);
|
|
273
|
-
}
|
|
274
|
-
if (onboardingPreflight.importPlan.suggestion_count > 0) {
|
|
275
|
-
console.log('');
|
|
276
|
-
console.log(`Next step: run 'brainclaw bootstrap --apply' to import ${onboardingPreflight.importPlan.suggestion_count} suggested item(s) into canonical memory.`);
|
|
277
|
-
console.log(`Rollback: run 'brainclaw bootstrap --uninstall' to deactivate the last bootstrap-managed import.`);
|
|
278
|
-
}
|
|
279
|
-
if ((onboardingPreflight.importPlan.interview?.question_count ?? 0) > 0) {
|
|
280
|
-
console.log('');
|
|
281
|
-
console.log(`Interview: run 'brainclaw bootstrap --interview --audience cli' for terminal agents or '--audience ide_chat' for IDE chat agents.`);
|
|
282
|
-
console.log(`Apply confirmed answers: write a JSON answers file and run 'brainclaw bootstrap --answers-file <path> --apply'.`);
|
|
340
|
+
if (emptyMemoryRec.route === 'ideate') {
|
|
341
|
+
console.log(`Onboarding: ${emptyMemoryRec.text}`);
|
|
283
342
|
}
|
|
284
|
-
else
|
|
285
|
-
|
|
286
|
-
console.log(
|
|
343
|
+
else {
|
|
344
|
+
const onboardingPreflight = runBootstrapProfile({ cwd, refresh: true });
|
|
345
|
+
console.log('Onboarding preflight:');
|
|
346
|
+
console.log(` ${emptyMemoryRec.text}`);
|
|
347
|
+
for (const line of renderBootstrapSummary(onboardingPreflight).split('\n')) {
|
|
348
|
+
console.log(` ${line}`);
|
|
349
|
+
}
|
|
350
|
+
if (onboardingPreflight.importPlan.suggestion_count > 0) {
|
|
351
|
+
console.log('');
|
|
352
|
+
console.log(`Next step: run 'brainclaw bootstrap --apply' to import ${onboardingPreflight.importPlan.suggestion_count} suggested item(s) into canonical memory.`);
|
|
353
|
+
console.log(`Rollback: run 'brainclaw bootstrap --uninstall' to deactivate the last bootstrap-managed import.`);
|
|
354
|
+
}
|
|
355
|
+
if ((onboardingPreflight.importPlan.interview?.question_count ?? 0) > 0) {
|
|
356
|
+
console.log('');
|
|
357
|
+
console.log(`Interview: run 'brainclaw bootstrap --interview --audience cli' for terminal agents or '--audience ide_chat' for IDE chat agents.`);
|
|
358
|
+
console.log(`Apply confirmed answers: write a JSON answers file and run 'brainclaw bootstrap --answers-file <path> --apply'.`);
|
|
359
|
+
}
|
|
360
|
+
else if ((onboardingPreflight.profile.gaps?.length ?? 0) > 0) {
|
|
361
|
+
console.log('');
|
|
362
|
+
console.log(`Next step: review the onboarding gaps, then use 'brainclaw bootstrap --json' as the basis for an interview/import flow.`);
|
|
363
|
+
}
|
|
287
364
|
}
|
|
288
365
|
}
|
|
289
366
|
console.log('');
|
|
@@ -293,7 +370,16 @@ export async function runInit(options = {}) {
|
|
|
293
370
|
else {
|
|
294
371
|
console.log(`Tip: run 'brainclaw init' again later to refresh the detected agent's integration files on this project.`);
|
|
295
372
|
}
|
|
296
|
-
console.log(`Tip:
|
|
373
|
+
console.log(`Tip: in an agent session, call the bclaw_work MCP tool (intent: "consult") to load the shared memory; from a terminal, 'brainclaw context --json' does the same.`);
|
|
374
|
+
}
|
|
375
|
+
function safeRunMachinePrereqs(agentName) {
|
|
376
|
+
try {
|
|
377
|
+
return runGlobalInstall([agentName]);
|
|
378
|
+
}
|
|
379
|
+
catch {
|
|
380
|
+
// Non-fatal: machine-scope writes are best-effort, never block init.
|
|
381
|
+
return [];
|
|
382
|
+
}
|
|
297
383
|
}
|
|
298
384
|
function installPostMergeHookIfMissing(cwd) {
|
|
299
385
|
try {
|
|
@@ -483,6 +569,12 @@ function buildInitConfig(input) {
|
|
|
483
569
|
storageDir: input.storageDir,
|
|
484
570
|
topology: input.topology,
|
|
485
571
|
ignoreStrategy: input.ignoreStrategy,
|
|
572
|
+
// Solo-agent fresh default: the human running init is the default curator.
|
|
573
|
+
// Without it, approval_policy=review + curators=[] = every candidate sits
|
|
574
|
+
// in pending forever — a surprise the 2026-06-10 front-door audit flagged.
|
|
575
|
+
// mergeConfigWithDefaults preserves any explicit curators list on an
|
|
576
|
+
// existing store, so this only takes effect on fresh installs.
|
|
577
|
+
curatorName: input.currentAgent.name,
|
|
486
578
|
});
|
|
487
579
|
const config = input.existingConfig
|
|
488
580
|
? mergeConfigWithDefaults(input.existingConfig, fallbackConfig)
|
|
@@ -512,6 +604,16 @@ function buildInitConfig(input) {
|
|
|
512
604
|
max_items_per_section: Math.min(markdown.max_items_per_section, 20),
|
|
513
605
|
};
|
|
514
606
|
}
|
|
607
|
+
// pln#567 (decision A) — the event journal is ON by default for projects
|
|
608
|
+
// created through init. Set HERE, never in defaultConfig:
|
|
609
|
+
// createTestWorkspace builds its config straight from defaultConfig, so a dual
|
|
610
|
+
// default there would make the whole core suite dual-write (trp_65176454).
|
|
611
|
+
// Existing stores keep their current value, including unset legacy configs:
|
|
612
|
+
// `migrate --enable-journal` is the explicit path that turns them on and
|
|
613
|
+
// backfills genesis before future dual-writes depend on the journal.
|
|
614
|
+
if (input.defaultJournalMode === true && config.store?.journal?.mode === undefined) {
|
|
615
|
+
config.store = { ...config.store, journal: { ...config.store?.journal, mode: 'dual' } };
|
|
616
|
+
}
|
|
515
617
|
return config;
|
|
516
618
|
}
|
|
517
619
|
function mergeConfigWithDefaults(existingConfig, fallbackConfig) {
|
|
@@ -40,63 +40,63 @@ export function runInstallHooks(options = {}) {
|
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
function generateClaudePreToolScript() {
|
|
43
|
-
return `#!/bin/sh
|
|
44
|
-
# brainclaw Claude Code preToolUse hook
|
|
45
|
-
# Generated by: brainclaw install-hooks
|
|
46
|
-
exec node -e "
|
|
47
|
-
const fs = require('fs');
|
|
48
|
-
const path = require('path');
|
|
49
|
-
const { execSync } = require('child_process');
|
|
50
|
-
|
|
51
|
-
const toolName = process.env.CLAUDE_TOOL_NAME || process.argv[2] || process.env.TOOL_NAME || '';
|
|
52
|
-
const isWrite = /edit|write|replace|bash|str_replace/i.test(toolName);
|
|
53
|
-
|
|
54
|
-
if (!isWrite || !toolName) process.exit(0);
|
|
55
|
-
|
|
56
|
-
try {
|
|
57
|
-
const BCLAW_CMD = fs.existsSync(path.join(process.cwd(), 'node_modules', '.bin', 'brainclaw'))
|
|
58
|
-
? 'npx brainclaw' : 'brainclaw';
|
|
59
|
-
const out = execSync(BCLAW_CMD + ' claim list --json', { encoding: 'utf8', stdio: ['pipe', 'pipe', 'ignore'] });
|
|
60
|
-
const claims = JSON.parse(out);
|
|
61
|
-
if (claims && claims.length > 0) process.exit(0);
|
|
62
|
-
} catch (e) {
|
|
63
|
-
// ignore if brainclaw not found or fails
|
|
64
|
-
process.exit(0);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const sessionMark = path.join(process.cwd(), '.brainclaw', 'tmp', 'claude_warned');
|
|
68
|
-
if (!fs.existsSync(path.dirname(sessionMark))) fs.mkdirSync(path.dirname(sessionMark), { recursive: true });
|
|
69
|
-
|
|
70
|
-
if (fs.existsSync(sessionMark)) {
|
|
71
|
-
const mtime = fs.statSync(sessionMark).mtimeMs;
|
|
72
|
-
if (Date.now() - mtime < 2 * 60 * 60 * 1000) {
|
|
73
|
-
process.exit(0); // already warned this session
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
fs.writeFileSync(sessionMark, Date.now().toString());
|
|
77
|
-
|
|
78
|
-
process.stderr.write('\\n[Brainclaw] ⚠️ WARNING: You are about to use an Edit/Write tool (' + toolName + ') but you have NO active claim.\\n');
|
|
79
|
-
process.stderr.write('[Brainclaw] Consider running \\\`brainclaw claim create <scope>\\\` to lock your work and avoid conflicts.\\n\\n');
|
|
80
|
-
" 2>&1 || exit 0
|
|
43
|
+
return `#!/bin/sh
|
|
44
|
+
# brainclaw Claude Code preToolUse hook
|
|
45
|
+
# Generated by: brainclaw install-hooks
|
|
46
|
+
exec node -e "
|
|
47
|
+
const fs = require('fs');
|
|
48
|
+
const path = require('path');
|
|
49
|
+
const { execSync } = require('child_process');
|
|
50
|
+
|
|
51
|
+
const toolName = process.env.CLAUDE_TOOL_NAME || process.argv[2] || process.env.TOOL_NAME || '';
|
|
52
|
+
const isWrite = /edit|write|replace|bash|str_replace/i.test(toolName);
|
|
53
|
+
|
|
54
|
+
if (!isWrite || !toolName) process.exit(0);
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
const BCLAW_CMD = fs.existsSync(path.join(process.cwd(), 'node_modules', '.bin', 'brainclaw'))
|
|
58
|
+
? 'npx brainclaw' : 'brainclaw';
|
|
59
|
+
const out = execSync(BCLAW_CMD + ' claim list --json', { encoding: 'utf8', stdio: ['pipe', 'pipe', 'ignore'] });
|
|
60
|
+
const claims = JSON.parse(out);
|
|
61
|
+
if (claims && claims.length > 0) process.exit(0);
|
|
62
|
+
} catch (e) {
|
|
63
|
+
// ignore if brainclaw not found or fails
|
|
64
|
+
process.exit(0);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const sessionMark = path.join(process.cwd(), '.brainclaw', 'tmp', 'claude_warned');
|
|
68
|
+
if (!fs.existsSync(path.dirname(sessionMark))) fs.mkdirSync(path.dirname(sessionMark), { recursive: true });
|
|
69
|
+
|
|
70
|
+
if (fs.existsSync(sessionMark)) {
|
|
71
|
+
const mtime = fs.statSync(sessionMark).mtimeMs;
|
|
72
|
+
if (Date.now() - mtime < 2 * 60 * 60 * 1000) {
|
|
73
|
+
process.exit(0); // already warned this session
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
fs.writeFileSync(sessionMark, Date.now().toString());
|
|
77
|
+
|
|
78
|
+
process.stderr.write('\\n[Brainclaw] ⚠️ WARNING: You are about to use an Edit/Write tool (' + toolName + ') but you have NO active claim.\\n');
|
|
79
|
+
process.stderr.write('[Brainclaw] Consider running \\\`brainclaw claim create <scope>\\\` to lock your work and avoid conflicts.\\n\\n');
|
|
80
|
+
" 2>&1 || exit 0
|
|
81
81
|
`;
|
|
82
82
|
}
|
|
83
83
|
function generatePostMergeScript() {
|
|
84
|
-
return `#!/bin/sh
|
|
85
|
-
# brainclaw post-merge hook
|
|
86
|
-
# Auto-releases claims whose scope overlaps with files changed by the merge
|
|
87
|
-
# Generated by: brainclaw install-hooks
|
|
88
|
-
|
|
89
|
-
BCLAW_CMD=""
|
|
90
|
-
if command -v brainclaw >/dev/null 2>&1; then
|
|
91
|
-
BCLAW_CMD="brainclaw"
|
|
92
|
-
elif command -v bclaw >/dev/null 2>&1; then
|
|
93
|
-
BCLAW_CMD="bclaw"
|
|
94
|
-
else
|
|
95
|
-
BCLAW_CMD="npx --no brainclaw"
|
|
96
|
-
fi
|
|
97
|
-
|
|
98
|
-
$BCLAW_CMD release-claims --from-git-diff 2>/dev/null || true
|
|
99
|
-
$BCLAW_CMD worktree clean 2>/dev/null || true
|
|
84
|
+
return `#!/bin/sh
|
|
85
|
+
# brainclaw post-merge hook
|
|
86
|
+
# Auto-releases claims whose scope overlaps with files changed by the merge
|
|
87
|
+
# Generated by: brainclaw install-hooks
|
|
88
|
+
|
|
89
|
+
BCLAW_CMD=""
|
|
90
|
+
if command -v brainclaw >/dev/null 2>&1; then
|
|
91
|
+
BCLAW_CMD="brainclaw"
|
|
92
|
+
elif command -v bclaw >/dev/null 2>&1; then
|
|
93
|
+
BCLAW_CMD="bclaw"
|
|
94
|
+
else
|
|
95
|
+
BCLAW_CMD="npx --no brainclaw"
|
|
96
|
+
fi
|
|
97
|
+
|
|
98
|
+
$BCLAW_CMD release-claims --from-git-diff 2>/dev/null || true
|
|
99
|
+
$BCLAW_CMD worktree clean 2>/dev/null || true
|
|
100
100
|
`;
|
|
101
101
|
}
|
|
102
102
|
function findGitRoot(cwd) {
|
|
@@ -113,30 +113,30 @@ function findGitRoot(cwd) {
|
|
|
113
113
|
function generateHookScript() {
|
|
114
114
|
// Use node directly to avoid sh.exe pipe issues on Windows (SIGPIPE).
|
|
115
115
|
// The script is a self-contained node -e that runs both checks.
|
|
116
|
-
return `#!/bin/sh
|
|
117
|
-
# brainclaw pre-commit hook — generated by brainclaw install-hooks
|
|
118
|
-
# Runs via node to avoid sh.exe SIGPIPE issues on Windows.
|
|
119
|
-
exec node -e "
|
|
120
|
-
const { execSync } = require('child_process');
|
|
121
|
-
const staged = execSync('git diff --cached --name-only', { encoding: 'utf-8' }).trim();
|
|
122
|
-
if (!staged) process.exit(0);
|
|
123
|
-
|
|
124
|
-
// Check 1: reject staged .brainclaw/ files
|
|
125
|
-
const brainclawFiles = staged.split('\\\\n').filter(f => f.startsWith('.brainclaw/'));
|
|
126
|
-
if (brainclawFiles.length > 0) {
|
|
127
|
-
process.stderr.write('\\\\nbrainclaw: .brainclaw/ files are staged — blocked.\\\\n');
|
|
128
|
-
brainclawFiles.forEach(f => process.stderr.write(' ' + f + '\\\\n'));
|
|
129
|
-
process.stderr.write(' Fix: git reset HEAD .brainclaw/\\\\n\\\\n');
|
|
130
|
-
process.exit(1);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// Check 2: active constraint violations
|
|
134
|
-
try {
|
|
135
|
-
execSync('brainclaw check-constraints --staged', { stdio: 'inherit' });
|
|
136
|
-
} catch (e) {
|
|
137
|
-
if (e.status) process.exit(e.status);
|
|
138
|
-
}
|
|
139
|
-
" 2>&1 || exit $?
|
|
116
|
+
return `#!/bin/sh
|
|
117
|
+
# brainclaw pre-commit hook — generated by brainclaw install-hooks
|
|
118
|
+
# Runs via node to avoid sh.exe SIGPIPE issues on Windows.
|
|
119
|
+
exec node -e "
|
|
120
|
+
const { execSync } = require('child_process');
|
|
121
|
+
const staged = execSync('git diff --cached --name-only', { encoding: 'utf-8' }).trim();
|
|
122
|
+
if (!staged) process.exit(0);
|
|
123
|
+
|
|
124
|
+
// Check 1: reject staged .brainclaw/ files
|
|
125
|
+
const brainclawFiles = staged.split('\\\\n').filter(f => f.startsWith('.brainclaw/'));
|
|
126
|
+
if (brainclawFiles.length > 0) {
|
|
127
|
+
process.stderr.write('\\\\nbrainclaw: .brainclaw/ files are staged — blocked.\\\\n');
|
|
128
|
+
brainclawFiles.forEach(f => process.stderr.write(' ' + f + '\\\\n'));
|
|
129
|
+
process.stderr.write(' Fix: git reset HEAD .brainclaw/\\\\n\\\\n');
|
|
130
|
+
process.exit(1);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Check 2: active constraint violations
|
|
134
|
+
try {
|
|
135
|
+
execSync('brainclaw check-constraints --staged', { stdio: 'inherit' });
|
|
136
|
+
} catch (e) {
|
|
137
|
+
if (e.status) process.exit(e.status);
|
|
138
|
+
}
|
|
139
|
+
" 2>&1 || exit $?
|
|
140
140
|
`;
|
|
141
141
|
}
|
|
142
142
|
//# sourceMappingURL=install-hooks.js.map
|
|
@@ -284,6 +284,7 @@ export function handleBclawLoop(options) {
|
|
|
284
284
|
input: req.input,
|
|
285
285
|
dispatch: req.dispatch,
|
|
286
286
|
assignment_id: req.assignment_id,
|
|
287
|
+
claim_id: req.claim_id,
|
|
287
288
|
actor,
|
|
288
289
|
}, options.cwd);
|
|
289
290
|
const newEvents = findNewLoopEvents(loop.id, beforeEvents, options.cwd);
|
|
@@ -309,6 +310,9 @@ export function handleBclawLoop(options) {
|
|
|
309
310
|
: undefined,
|
|
310
311
|
actor,
|
|
311
312
|
caller_agent_id: req.agentId,
|
|
313
|
+
// pln#562 step 4 — a dispatched instance proves itself via its
|
|
314
|
+
// claim env; claim-bound slots reject same-named siblings.
|
|
315
|
+
caller_claim_id: process.env.BRAINCLAW_CLAIM_ID?.trim() || undefined,
|
|
312
316
|
}, options.cwd);
|
|
313
317
|
const newEvents = findNewLoopEvents(loop.id, beforeEvents, options.cwd);
|
|
314
318
|
return successResponse('complete_turn', { loop, next_expected: computeNextExpected(loop) }, [loopArtifactEntry(loop.id), ...loopEventArtifacts(newEvents)], [sideEffectUpdate('loop', loop.id), ...loopEventSideEffects(newEvents)], [], Date.now() - startMs, summarizeLoop(loop));
|