brainclaw 1.5.3 → 1.5.5
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/LICENSE +21 -74
- package/README.md +62 -38
- package/dist/brainclaw-vscode.vsix +0 -0
- package/dist/cli.js +72 -6
- package/dist/commands/assignment-resource.js +182 -0
- package/dist/commands/init.js +158 -22
- package/dist/commands/mcp-read-handlers.js +8 -4
- package/dist/commands/mcp-schemas.generated.js +196 -1
- package/dist/commands/mcp.js +12 -5
- package/dist/commands/setup.js +87 -48
- package/dist/commands/switch.js +4 -0
- package/dist/core/agentruns.js +10 -0
- package/dist/core/assignments.js +29 -10
- package/dist/core/context.js +1 -1
- package/dist/core/coordination.js +1 -1
- package/dist/core/entity-operations.js +38 -1
- package/dist/core/entity-registry.js +11 -10
- package/dist/core/schema.js +3 -0
- package/dist/core/store-resolution.js +26 -16
- package/dist/facts.js +3 -3
- package/dist/facts.json +2 -2
- package/docs/cli.md +115 -30
- package/docs/integrations/agents.md +14 -14
- package/docs/integrations/codex.md +15 -12
- package/docs/integrations/mcp.md +10 -4
- package/docs/integrations/overview.md +12 -3
- package/docs/mcp-schema-changelog.md +1 -1
- package/docs/playbooks/productivity/index.md +3 -3
- package/docs/product/positioning.md +10 -10
- package/docs/quickstart-existing-project.md +48 -28
- package/docs/quickstart.md +42 -28
- package/package.json +2 -2
package/LICENSE
CHANGED
|
@@ -1,74 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
Change Date: Four years after the release date of each version
|
|
23
|
-
Change License: MIT License
|
|
24
|
-
|
|
25
|
-
---
|
|
26
|
-
|
|
27
|
-
Notice
|
|
28
|
-
|
|
29
|
-
The Business Source License (this document, or the "License") is not an Open Source
|
|
30
|
-
license. However, the Licensed Work will eventually be made available under an Open
|
|
31
|
-
Source License, as stated in this License.
|
|
32
|
-
|
|
33
|
-
Use Limitation: The additional use grant in the Parameters specifies the permitted
|
|
34
|
-
production use. If your use case falls outside that grant, you need a separate
|
|
35
|
-
commercial license from the Licensor.
|
|
36
|
-
|
|
37
|
-
License text
|
|
38
|
-
|
|
39
|
-
The Licensor hereby grants you the right to copy, modify, create derivative works,
|
|
40
|
-
redistribute, and make non-production use of the Licensed Work. The Licensor may
|
|
41
|
-
make an Additional Use Grant, above, permitting limited production use.
|
|
42
|
-
|
|
43
|
-
Effective on the Change Date, or the fourth anniversary of the first publicly available
|
|
44
|
-
distribution of a specific version of the Licensed Work under this License, whichever
|
|
45
|
-
comes first, the Licensor hereby grants you rights under the terms of the Change
|
|
46
|
-
License, and the rights granted in the paragraph above terminate.
|
|
47
|
-
|
|
48
|
-
If your use of the Licensed Work does not comply with the requirements currently in
|
|
49
|
-
effect as described in this License, you must purchase a commercial license from the
|
|
50
|
-
Licensor, its affiliated entities, or authorized resellers, or you must refrain from
|
|
51
|
-
using the Licensed Work.
|
|
52
|
-
|
|
53
|
-
All copies of the original and modified Licensed Work, and derivative works of the
|
|
54
|
-
Licensed Work, are subject to this License. This License applies separately for each
|
|
55
|
-
version of the Licensed Work and the Change Date may vary for each version of the
|
|
56
|
-
Licensed Work released by the licensor.
|
|
57
|
-
|
|
58
|
-
You must conspicuously display this License on each original or modified copy of the
|
|
59
|
-
Licensed Work. If you receive the Licensed Work in original or modified form from a
|
|
60
|
-
third party, the terms and conditions set forth in this License apply to your use of
|
|
61
|
-
that work.
|
|
62
|
-
|
|
63
|
-
Any use of the Licensed Work in violation of this License will automatically terminate
|
|
64
|
-
your rights under this License for the current and all future versions of the Licensed
|
|
65
|
-
Work.
|
|
66
|
-
|
|
67
|
-
This License does not grant you any right in any trademark or logo of Licensor or its
|
|
68
|
-
affiliates (provided that you may use a trademark or logo of Licensor as expressly
|
|
69
|
-
required by this License).
|
|
70
|
-
|
|
71
|
-
TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON AN "AS
|
|
72
|
-
IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS OR
|
|
73
|
-
IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
74
|
-
PARTICULAR PURPOSE, NON-INFRINGEMENT, AND TITLE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024-2026 Juan Berdah
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -108,28 +108,52 @@ If you want the least surprising setup today, use Linux first. If you are on Win
|
|
|
108
108
|
|
|
109
109
|
---
|
|
110
110
|
|
|
111
|
-
## Get Started
|
|
112
|
-
|
|
113
|
-
### 1.
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
111
|
+
## Get Started
|
|
112
|
+
|
|
113
|
+
### 1. Let your coding agent lead
|
|
114
|
+
|
|
115
|
+
The smoothest first-run path is agent-first:
|
|
116
|
+
|
|
117
|
+
1. ask your coding agent to inspect the package and explain what brainclaw does
|
|
118
|
+
2. ask it to install brainclaw and initialize or join the project you're working on
|
|
119
|
+
3. use the CLI yourself when you need an explicit operator or fallback path
|
|
120
|
+
|
|
121
|
+
If you want to drive setup manually, use the steps below.
|
|
122
|
+
|
|
123
|
+
### 2. Install
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
npm install -g brainclaw
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### 3. Bootstrap this machine
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
brainclaw setup-machine --yes
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
This detects the installed agents on the current machine, writes the machine-level MCP and user config Brainclaw manages, and does **not** scan or initialize repositories.
|
|
136
|
+
|
|
137
|
+
### 4. Initialize or refresh the current project
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
cd your-project
|
|
141
|
+
brainclaw init
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
`brainclaw init` is now safe to rerun. It creates `.brainclaw/` when the project is new, or refreshes the managed Brainclaw and agent integration files when the project already has memory.
|
|
145
|
+
|
|
146
|
+
If you are explicitly adding another agent to an existing Brainclaw project, use:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
brainclaw enable-agent <agent-name>
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### 5. Restart your agent
|
|
153
|
+
|
|
154
|
+
Restart your coding agent (or reload MCP servers) so it picks up the new configuration. After that, brainclaw tools are available.
|
|
155
|
+
|
|
156
|
+
### 6. Start working
|
|
133
157
|
|
|
134
158
|
Pick one of the canonical entry points depending on what you're doing:
|
|
135
159
|
|
|
@@ -161,7 +185,7 @@ For agents without MCP (e.g. Copilot reads `.github/copilot-instructions.md`), r
|
|
|
161
185
|
brainclaw export --detect --write
|
|
162
186
|
```
|
|
163
187
|
|
|
164
|
-
###
|
|
188
|
+
### 7. Verify it works
|
|
165
189
|
|
|
166
190
|
```bash
|
|
167
191
|
brainclaw status # see active sessions, claims, plans
|
|
@@ -172,11 +196,11 @@ brainclaw agent-board # see what each agent is doing
|
|
|
172
196
|
|
|
173
197
|
To configure brainclaw for all your repos and agents at once:
|
|
174
198
|
|
|
175
|
-
```bash
|
|
176
|
-
brainclaw setup --yes
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
This
|
|
199
|
+
```bash
|
|
200
|
+
brainclaw setup --yes
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
This is the broader multi-repo wizard. It bootstraps the machine, scans your project roots, and initializes selected repositories in one pass.
|
|
180
204
|
|
|
181
205
|
### Existing projects
|
|
182
206
|
|
|
@@ -380,15 +404,15 @@ For older releases (v0.x and the early v1.0 launch series), `git log` on `master
|
|
|
380
404
|
|
|
381
405
|
---
|
|
382
406
|
|
|
383
|
-
## License
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
The
|
|
388
|
-
|
|
389
|
-
- the local-first brainclaw core is
|
|
390
|
-
- cloud shared-memory, remote collaboration services, advanced dashboards, and related hosted add-ons will live in separate commercial products
|
|
391
|
-
|
|
392
|
-
The
|
|
407
|
+
## License
|
|
408
|
+
|
|
409
|
+
brainclaw core is published under the [MIT License](LICENSE) — (c) 2024-2026 Juan Berdah.
|
|
410
|
+
|
|
411
|
+
The licensing split is simple:
|
|
412
|
+
|
|
413
|
+
- the local-first brainclaw core is MIT
|
|
414
|
+
- cloud shared-memory, remote collaboration services, advanced dashboards, and related hosted add-ons will live in separate commercial products
|
|
415
|
+
|
|
416
|
+
The MIT core covers what makes brainclaw useful inside a repo today: local project memory, local MCP and CLI coordination, onboarding and bootstrap, plans, claims, handoffs, runtime notes, and local agent integrations.
|
|
393
417
|
|
|
394
418
|
The goal is not to close brainclaw down. The goal is to keep the local-first core open and genuinely useful on its own, while keeping hosted collaboration features separate.
|
|
Binary file
|
package/dist/cli.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { Command } from 'commander';
|
|
4
4
|
import { runInit } from './commands/init.js';
|
|
5
|
-
import { runSetup } from './commands/setup.js';
|
|
5
|
+
import { runSetup, runSetupMachine } from './commands/setup.js';
|
|
6
6
|
import { runUpgrade } from './commands/upgrade.js';
|
|
7
7
|
import { patchAllMcpConfigs } from './core/agent-files.js';
|
|
8
8
|
import { runReconcile } from './commands/reconcile.js';
|
|
@@ -47,6 +47,7 @@ import { cleanupStaleCandidates } from './core/candidates.js';
|
|
|
47
47
|
import { runListClaims } from './commands/list-claims.js';
|
|
48
48
|
import { runReleaseClaim } from './commands/release-claim.js';
|
|
49
49
|
import { runClaimResource } from './commands/claim-resource.js';
|
|
50
|
+
import { runAssignmentResource } from './commands/assignment-resource.js';
|
|
50
51
|
import { runMemoryCommand } from './commands/memory.js';
|
|
51
52
|
import { runReleaseClaims } from './commands/release-claims.js';
|
|
52
53
|
import { runAgentBoard } from './commands/agent-board.js';
|
|
@@ -109,6 +110,42 @@ const program = new Command();
|
|
|
109
110
|
function collect(value, previous) {
|
|
110
111
|
return [...previous, value];
|
|
111
112
|
}
|
|
113
|
+
function parseLeadingGlobalOptions(argv) {
|
|
114
|
+
const result = {};
|
|
115
|
+
for (let i = 0; i < argv.length; i++) {
|
|
116
|
+
const token = argv[i];
|
|
117
|
+
if (!token.startsWith('-')) {
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
if (token === '--verbose') {
|
|
121
|
+
result.verbose = true;
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
if (token === '--debug') {
|
|
125
|
+
result.debug = true;
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
if (token === '--cwd') {
|
|
129
|
+
result.cwd = argv[i + 1];
|
|
130
|
+
i++;
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
if (token.startsWith('--cwd=')) {
|
|
134
|
+
result.cwd = token.slice('--cwd='.length);
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
if (token === '--project') {
|
|
138
|
+
result.project = argv[i + 1];
|
|
139
|
+
i++;
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
if (token.startsWith('--project=')) {
|
|
143
|
+
result.project = token.slice('--project='.length);
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return result;
|
|
148
|
+
}
|
|
112
149
|
function isCodevEnabled() {
|
|
113
150
|
return process.env.BRAINCLAW_ENABLE_CODEV === '1';
|
|
114
151
|
}
|
|
@@ -121,11 +158,11 @@ program
|
|
|
121
158
|
.option('--cwd <path>', 'Override working directory for this invocation')
|
|
122
159
|
.option('--project <name>', 'Run the command against a linked project (cross_project_links or workspace store-chain child). Resolves via resolveProjectCwd; mutually exclusive with --cwd.')
|
|
123
160
|
.hook('preAction', (_thisCommand, actionCommand) => {
|
|
124
|
-
const root =
|
|
161
|
+
const root = parseLeadingGlobalOptions(process.argv.slice(2));
|
|
125
162
|
initLogLevel({ verbose: root.verbose, debug: root.debug });
|
|
126
163
|
// Skip effective cwd resolution for commands that create the store
|
|
127
164
|
const cmdName = actionCommand.name();
|
|
128
|
-
const skipResolution = cmdName === 'init' || cmdName === 'setup';
|
|
165
|
+
const skipResolution = cmdName === 'init' || cmdName === 'setup' || cmdName === 'setup-machine';
|
|
129
166
|
// pln#359 phase 1c — `--project <name>` resolves a linked project to an
|
|
130
167
|
// absolute path via resolveProjectCwd, then feeds the same chdir flow
|
|
131
168
|
// as --cwd. Mutually exclusive with --cwd to avoid ambiguity.
|
|
@@ -165,9 +202,9 @@ program
|
|
|
165
202
|
// --- init ---
|
|
166
203
|
program
|
|
167
204
|
.command('init')
|
|
168
|
-
.description('Initialize project memory in .brainclaw/ storage directory')
|
|
205
|
+
.description('Initialize or refresh project memory in .brainclaw/ storage directory')
|
|
169
206
|
.option('-y, --yes', 'Skip interactive wizard and use defaults')
|
|
170
|
-
.option('--force', '
|
|
207
|
+
.option('--force', 'Rebuild managed Brainclaw config and generated files from defaults')
|
|
171
208
|
.option('--compact', 'Enable compact markdown mode')
|
|
172
209
|
.option('--topology <mode>', 'Topology mode: embedded, sidecar, local-only')
|
|
173
210
|
.option('--project-mode <mode>', 'Project mode: single-project, multi-project, auto')
|
|
@@ -181,7 +218,7 @@ program
|
|
|
181
218
|
// --- setup ---
|
|
182
219
|
program
|
|
183
220
|
.command('setup')
|
|
184
|
-
.description('Interactive onboarding wizard —
|
|
221
|
+
.description('Interactive onboarding wizard — machine bootstrap plus multi-repo init')
|
|
185
222
|
.option('--roots <paths>', 'Comma-separated root directories to scan (skips interactive prompt)')
|
|
186
223
|
.option('--agents <agents>', 'Agents to configure: all, detected, or comma-separated names')
|
|
187
224
|
.option('--repos <mode>', 'Repo selection: all, current, or comma-separated numbers')
|
|
@@ -189,6 +226,15 @@ program
|
|
|
189
226
|
.action(async (options) => {
|
|
190
227
|
await runSetup(options);
|
|
191
228
|
});
|
|
229
|
+
// --- setup-machine ---
|
|
230
|
+
program
|
|
231
|
+
.command('setup-machine')
|
|
232
|
+
.description('Machine-only onboarding — detect/configure agents and MCP without scanning or initializing repositories')
|
|
233
|
+
.option('--agents <agents>', 'Agents to configure: all, detected, or comma-separated names')
|
|
234
|
+
.option('-y, --yes', 'Accept all defaults non-interactively')
|
|
235
|
+
.action(async (options) => {
|
|
236
|
+
await runSetupMachine(options);
|
|
237
|
+
});
|
|
192
238
|
// --- memory-log ---
|
|
193
239
|
program
|
|
194
240
|
.command('memory-log')
|
|
@@ -1003,6 +1049,26 @@ program
|
|
|
1003
1049
|
.action((subcommand, args, options) => {
|
|
1004
1050
|
runClaimResource(subcommand, args, { ...options, planStatus: options.planStatus, localOnly: options.localOnly });
|
|
1005
1051
|
});
|
|
1052
|
+
// --- assignment ---
|
|
1053
|
+
program
|
|
1054
|
+
.command('assignment <subcommand> [args...]')
|
|
1055
|
+
.description('Manage work assignments (list, show, update, cancel)')
|
|
1056
|
+
.option('--json', 'Output as JSON for list/show')
|
|
1057
|
+
.option('--all', 'Include terminal assignments in list')
|
|
1058
|
+
.option('--status <status>', 'Status filter for list or target status for update')
|
|
1059
|
+
.option('--agent <agent>', 'Filter by agent name')
|
|
1060
|
+
.option('--claim <id>', 'Filter by linked claim ID')
|
|
1061
|
+
.option('--plan <id>', 'Filter by linked plan ID')
|
|
1062
|
+
.option('--sequence <id>', 'Filter by linked sequence ID')
|
|
1063
|
+
.option('--reason <text>', 'Optional status reason for update/cancel')
|
|
1064
|
+
.action((subcommand, args, options) => {
|
|
1065
|
+
runAssignmentResource(subcommand, args, {
|
|
1066
|
+
...options,
|
|
1067
|
+
claim: options.claim,
|
|
1068
|
+
plan: options.plan,
|
|
1069
|
+
sequence: options.sequence,
|
|
1070
|
+
});
|
|
1071
|
+
});
|
|
1006
1072
|
// --- list-claims ---
|
|
1007
1073
|
program
|
|
1008
1074
|
.command('list-claims')
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { memoryExists } from '../core/io.js';
|
|
2
|
+
import { listAssignments, loadAssignment, transitionAssignment } from '../core/assignments.js';
|
|
3
|
+
import { resolveCurrentAgentName } from '../core/agent-registry.js';
|
|
4
|
+
import { AssignmentStatusSchema } from '../core/schema.js';
|
|
5
|
+
const TERMINAL_STATUSES = new Set(['completed', 'cancelled', 'expired', 'rerouted']);
|
|
6
|
+
const KNOWN_SUBCOMMANDS = new Set(['list', 'ls', 'show', 'get', 'update', 'cancel']);
|
|
7
|
+
export function runAssignmentResource(subcommand, args, options = {}) {
|
|
8
|
+
const normalized = subcommand.trim().toLowerCase();
|
|
9
|
+
if (normalized === 'list' || normalized === 'ls') {
|
|
10
|
+
runListAssignmentsCommand(options);
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
if (normalized === 'show' || normalized === 'get') {
|
|
14
|
+
const id = args[0];
|
|
15
|
+
if (!id) {
|
|
16
|
+
console.error(`Error: assignment ${normalized} requires <id>.`);
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
runShowAssignmentCommand(id, options);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
if (normalized === 'update') {
|
|
23
|
+
const id = args[0];
|
|
24
|
+
if (!id) {
|
|
25
|
+
console.error('Error: assignment update requires <id>.');
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
const status = options.status;
|
|
29
|
+
if (!status) {
|
|
30
|
+
console.error('Error: assignment update requires --status <status>.');
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
runTransitionAssignmentCommand(id, status, options);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (normalized === 'cancel') {
|
|
37
|
+
const id = args[0];
|
|
38
|
+
if (!id) {
|
|
39
|
+
console.error('Error: assignment cancel requires <id>.');
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
runTransitionAssignmentCommand(id, 'cancelled', options);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (normalized.startsWith('asgn_') || KNOWN_SUBCOMMANDS.has(normalized)) {
|
|
46
|
+
console.error(`Error: unknown assignment subcommand "${subcommand}".`);
|
|
47
|
+
console.error(' Available: list, show, get, update, cancel');
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
console.error('Error: missing assignment subcommand.');
|
|
51
|
+
console.error(' Available: list, show, get, update, cancel');
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
function runListAssignmentsCommand(options) {
|
|
55
|
+
ensureInitialized(options.cwd);
|
|
56
|
+
const requestedStatus = parseAssignmentStatus(options.status);
|
|
57
|
+
let assignments = listAssignments(options.cwd, {
|
|
58
|
+
status: requestedStatus,
|
|
59
|
+
agent: options.agent,
|
|
60
|
+
claim_id: options.claim,
|
|
61
|
+
plan_id: options.plan,
|
|
62
|
+
sequence_id: options.sequence,
|
|
63
|
+
});
|
|
64
|
+
if (!options.all && !requestedStatus) {
|
|
65
|
+
assignments = assignments.filter((assignment) => !TERMINAL_STATUSES.has(assignment.status));
|
|
66
|
+
}
|
|
67
|
+
if (options.json) {
|
|
68
|
+
console.log(JSON.stringify(assignments, null, 2));
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (assignments.length === 0) {
|
|
72
|
+
console.log(options.all ? 'No assignments.' : 'No active assignments.');
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
console.log(`${assignments.length} ${options.all ? 'assignment(s)' : 'active assignment(s)'}:`);
|
|
76
|
+
console.log('');
|
|
77
|
+
for (const assignment of assignments) {
|
|
78
|
+
const extras = [];
|
|
79
|
+
if (assignment.plan_id)
|
|
80
|
+
extras.push(`plan ${assignment.plan_id}`);
|
|
81
|
+
if (assignment.claim_id)
|
|
82
|
+
extras.push(`claim ${assignment.claim_id}`);
|
|
83
|
+
if (assignment.sequence_id)
|
|
84
|
+
extras.push(`sequence ${assignment.sequence_id}`);
|
|
85
|
+
if (assignment.worktree_path)
|
|
86
|
+
extras.push(`worktree ${assignment.worktree_path}`);
|
|
87
|
+
const suffix = extras.length > 0 ? ` [${extras.join(', ')}]` : '';
|
|
88
|
+
console.log(` [${assignment.id}] ${assignment.agent} (${assignment.status}) -> ${assignment.scope}: ${assignment.description}${suffix}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function runShowAssignmentCommand(id, options) {
|
|
92
|
+
ensureInitialized(options.cwd);
|
|
93
|
+
const assignment = requireAssignment(id, options.cwd);
|
|
94
|
+
if (options.json) {
|
|
95
|
+
console.log(JSON.stringify(assignment, null, 2));
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
console.log(`Assignment: ${assignment.id}`);
|
|
99
|
+
console.log(` Agent: ${assignment.agent}`);
|
|
100
|
+
console.log(` Status: ${assignment.status}`);
|
|
101
|
+
console.log(` Scope: ${assignment.scope}`);
|
|
102
|
+
console.log(` Description: ${assignment.description}`);
|
|
103
|
+
console.log(` Claim: ${assignment.claim_id}`);
|
|
104
|
+
if (assignment.message_id)
|
|
105
|
+
console.log(` Message: ${assignment.message_id}`);
|
|
106
|
+
if (assignment.plan_id)
|
|
107
|
+
console.log(` Plan: ${assignment.plan_id}`);
|
|
108
|
+
if (assignment.sequence_id)
|
|
109
|
+
console.log(` Sequence: ${assignment.sequence_id}`);
|
|
110
|
+
if (assignment.session_id)
|
|
111
|
+
console.log(` Session: ${assignment.session_id}`);
|
|
112
|
+
if (assignment.status_reason)
|
|
113
|
+
console.log(` Reason: ${assignment.status_reason}`);
|
|
114
|
+
if (assignment.worktree_path)
|
|
115
|
+
console.log(` Worktree: ${assignment.worktree_path}`);
|
|
116
|
+
console.log(` Created: ${assignment.created_at}`);
|
|
117
|
+
if (assignment.updated_at)
|
|
118
|
+
console.log(` Updated: ${assignment.updated_at}`);
|
|
119
|
+
if (assignment.offered_at)
|
|
120
|
+
console.log(` Offered: ${assignment.offered_at}`);
|
|
121
|
+
if (assignment.accepted_at)
|
|
122
|
+
console.log(` Accepted: ${assignment.accepted_at}`);
|
|
123
|
+
if (assignment.started_at)
|
|
124
|
+
console.log(` Started: ${assignment.started_at}`);
|
|
125
|
+
if (assignment.completed_at)
|
|
126
|
+
console.log(` Completed: ${assignment.completed_at}`);
|
|
127
|
+
if (assignment.cancelled_at)
|
|
128
|
+
console.log(` Cancelled: ${assignment.cancelled_at}`);
|
|
129
|
+
if (assignment.failed_at)
|
|
130
|
+
console.log(` Failed: ${assignment.failed_at}`);
|
|
131
|
+
if (assignment.blocked_at)
|
|
132
|
+
console.log(` Blocked: ${assignment.blocked_at}`);
|
|
133
|
+
if (assignment.timed_out_at)
|
|
134
|
+
console.log(` Timed out: ${assignment.timed_out_at}`);
|
|
135
|
+
if (assignment.expired_at)
|
|
136
|
+
console.log(` Expired: ${assignment.expired_at}`);
|
|
137
|
+
if (assignment.rerouted_at)
|
|
138
|
+
console.log(` Rerouted: ${assignment.rerouted_at}`);
|
|
139
|
+
}
|
|
140
|
+
function runTransitionAssignmentCommand(id, statusInput, options) {
|
|
141
|
+
ensureInitialized(options.cwd);
|
|
142
|
+
const nextStatus = parseAssignmentStatus(statusInput, 'status');
|
|
143
|
+
const actor = resolveCurrentAgentName(options.cwd);
|
|
144
|
+
try {
|
|
145
|
+
const result = transitionAssignment(id, nextStatus, {
|
|
146
|
+
actor,
|
|
147
|
+
status_reason: options.reason,
|
|
148
|
+
}, options.cwd);
|
|
149
|
+
const verb = nextStatus === 'cancelled' ? 'cancelled' : 'updated';
|
|
150
|
+
console.log(`✔ Assignment ${verb}: [${result.assignment.id}] ${result.previous_status} -> ${result.assignment.status}`);
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
console.error(`Error: ${error.message}`);
|
|
154
|
+
process.exit(1);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
function ensureInitialized(cwd) {
|
|
158
|
+
if (!memoryExists(cwd)) {
|
|
159
|
+
console.error('Error: .brainclaw/ not found. Run `brainclaw init` first.');
|
|
160
|
+
process.exit(1);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function requireAssignment(id, cwd) {
|
|
164
|
+
const assignment = loadAssignment(id, cwd);
|
|
165
|
+
if (!assignment) {
|
|
166
|
+
console.error(`Error: assignment not found: ${id}`);
|
|
167
|
+
process.exit(1);
|
|
168
|
+
}
|
|
169
|
+
return assignment;
|
|
170
|
+
}
|
|
171
|
+
function parseAssignmentStatus(value, label = 'filter') {
|
|
172
|
+
if (value === undefined) {
|
|
173
|
+
return undefined;
|
|
174
|
+
}
|
|
175
|
+
const parsed = AssignmentStatusSchema.safeParse(value);
|
|
176
|
+
if (!parsed.success) {
|
|
177
|
+
console.error(`Error: invalid ${label} '${value}'. Expected one of: ${AssignmentStatusSchema.options.join(', ')}`);
|
|
178
|
+
process.exit(1);
|
|
179
|
+
}
|
|
180
|
+
return parsed.data;
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=assignment-resource.js.map
|