macro-agent 0.1.10 → 0.1.12
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/CLAUDE.md +97 -0
- package/dist/acp/macro-agent.d.ts.map +1 -1
- package/dist/acp/macro-agent.js +42 -6
- package/dist/acp/macro-agent.js.map +1 -1
- package/dist/adapters/tasks-adapter.d.ts.map +1 -1
- package/dist/adapters/tasks-adapter.js +3 -0
- package/dist/adapters/tasks-adapter.js.map +1 -1
- package/dist/adapters/types.d.ts +1 -0
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/agent/agent-manager-v2.d.ts.map +1 -1
- package/dist/agent/agent-manager-v2.js +74 -11
- package/dist/agent/agent-manager-v2.js.map +1 -1
- package/dist/agent/agent-store.d.ts +10 -0
- package/dist/agent/agent-store.d.ts.map +1 -1
- package/dist/agent/agent-store.js +22 -0
- package/dist/agent/agent-store.js.map +1 -1
- package/dist/boot-v2.d.ts +88 -1
- package/dist/boot-v2.d.ts.map +1 -1
- package/dist/boot-v2.js +343 -7
- package/dist/boot-v2.js.map +1 -1
- package/dist/cli/acp.js +4 -0
- package/dist/cli/acp.js.map +1 -1
- package/dist/lifecycle/cascade.d.ts +25 -2
- package/dist/lifecycle/cascade.d.ts.map +1 -1
- package/dist/lifecycle/cascade.js +70 -2
- package/dist/lifecycle/cascade.js.map +1 -1
- package/dist/map/cascade-action-handler.d.ts +24 -0
- package/dist/map/cascade-action-handler.d.ts.map +1 -0
- package/dist/map/cascade-action-handler.js +170 -0
- package/dist/map/cascade-action-handler.js.map +1 -0
- package/dist/map/cascade-bridge.d.ts.map +1 -1
- package/dist/map/cascade-bridge.js +42 -5
- package/dist/map/cascade-bridge.js.map +1 -1
- package/dist/map/coordination-handler.d.ts.map +1 -1
- package/dist/map/coordination-handler.js +12 -1
- package/dist/map/coordination-handler.js.map +1 -1
- package/dist/map/server.d.ts.map +1 -1
- package/dist/map/server.js +172 -1
- package/dist/map/server.js.map +1 -1
- package/dist/map/sidecar.d.ts.map +1 -1
- package/dist/map/sidecar.js +18 -2
- package/dist/map/sidecar.js.map +1 -1
- package/dist/map/types.d.ts +2 -0
- package/dist/map/types.d.ts.map +1 -1
- package/dist/teams/seed-defaults.d.ts.map +1 -1
- package/dist/teams/seed-defaults.js +6 -2
- package/dist/teams/seed-defaults.js.map +1 -1
- package/dist/teams/team-loader.d.ts.map +1 -1
- package/dist/teams/team-loader.js +17 -1
- package/dist/teams/team-loader.js.map +1 -1
- package/dist/workspace/git-cascade-adapter.d.ts +1 -1
- package/dist/workspace/git-cascade-adapter.d.ts.map +1 -1
- package/dist/workspace/git-cascade-adapter.js +26 -0
- package/dist/workspace/git-cascade-adapter.js.map +1 -1
- package/dist/workspace/landing/merge-to-parent.d.ts.map +1 -1
- package/dist/workspace/landing/merge-to-parent.js +1 -0
- package/dist/workspace/landing/merge-to-parent.js.map +1 -1
- package/dist/workspace/recovery/spawn-resolver.d.ts.map +1 -1
- package/dist/workspace/recovery/spawn-resolver.js +8 -1
- package/dist/workspace/recovery/spawn-resolver.js.map +1 -1
- package/dist/workspace/types-v3.d.ts +7 -0
- package/dist/workspace/types-v3.d.ts.map +1 -1
- package/dist/workspace/types-v3.js.map +1 -1
- package/dist/workspace/types.d.ts +17 -0
- package/dist/workspace/types.d.ts.map +1 -1
- package/dist/workspace/workspace-manager.d.ts +9 -0
- package/dist/workspace/workspace-manager.d.ts.map +1 -1
- package/dist/workspace/workspace-manager.js +45 -2
- package/dist/workspace/workspace-manager.js.map +1 -1
- package/docs/design/task-dispatcher.md +880 -0
- package/package.json +3 -3
- package/src/__tests__/boot-v2.test.ts +435 -0
- package/src/__tests__/e2e/acp-over-map.e2e.test.ts +92 -0
- package/src/__tests__/e2e/bootstrap.e2e.test.ts +319 -0
- package/src/__tests__/e2e/dispatch-coordination.e2e.test.ts +495 -0
- package/src/__tests__/e2e/dispatch-live.e2e.test.ts +564 -0
- package/src/__tests__/e2e/dispatch-opentasks.e2e.test.ts +496 -0
- package/src/__tests__/e2e/dispatch-phase2-live.e2e.test.ts +456 -0
- package/src/__tests__/e2e/dispatch-phase2.e2e.test.ts +386 -0
- package/src/__tests__/e2e/dispatch.e2e.test.ts +376 -0
- package/src/acp/macro-agent.ts +41 -6
- package/src/adapters/__tests__/tasks-adapter.test.ts +1 -0
- package/src/adapters/tasks-adapter.ts +3 -0
- package/src/adapters/types.ts +1 -0
- package/src/agent/__tests__/agent-store.test.ts +52 -0
- package/src/agent/agent-manager-v2.ts +79 -11
- package/src/agent/agent-store.ts +24 -0
- package/src/boot-v2.ts +522 -35
- package/src/cli/acp.ts +4 -0
- package/src/lifecycle/__tests__/cascade-consolidation.test.ts +240 -0
- package/src/lifecycle/cascade.ts +77 -2
- package/src/map/__tests__/emit-event.test.ts +71 -0
- package/src/map/cascade-action-handler.ts +205 -0
- package/src/map/cascade-bridge.ts +43 -5
- package/src/map/coordination-handler.ts +13 -1
- package/src/map/server.ts +178 -1
- package/src/map/sidecar.ts +19 -2
- package/src/map/types.ts +3 -0
- package/src/teams/seed-defaults.ts +6 -2
- package/src/teams/team-loader.ts +18 -1
- package/src/workspace/__tests__/land-dispatch.test.ts +214 -0
- package/src/workspace/__tests__/self-driving-yaml.test.ts +10 -2
- package/src/workspace/git-cascade-adapter.ts +30 -3
- package/src/workspace/landing/__tests__/strategies.test.ts +42 -0
- package/src/workspace/landing/merge-to-parent.ts +1 -0
- package/src/workspace/recovery/spawn-resolver.ts +8 -1
- package/src/workspace/types-v3.ts +7 -0
- package/src/workspace/types.ts +20 -0
- package/src/workspace/workspace-manager.ts +61 -2
- package/templates/teams/self-driving/team.yaml +142 -0
- package/tsconfig.json +2 -1
|
@@ -75,6 +75,48 @@ describe('landing strategies', () => {
|
|
|
75
75
|
expect.objectContaining({ targetStreamId: 'target-1' })
|
|
76
76
|
);
|
|
77
77
|
});
|
|
78
|
+
|
|
79
|
+
it('threads ctx.taskRef into mergeStream metadata when present', async () => {
|
|
80
|
+
const strategy = new MergeToParentStrategy();
|
|
81
|
+
const ws = {
|
|
82
|
+
listStreams: vi.fn(() => []),
|
|
83
|
+
mergeStream: vi.fn(() => ({ success: true, newHead: 'aaa' })),
|
|
84
|
+
} as unknown as WorkspaceManager;
|
|
85
|
+
|
|
86
|
+
const taskRef = { resource_id: 'res-a1', node_id: 'task-a1' };
|
|
87
|
+
await strategy.land({
|
|
88
|
+
agentId: 'agent-1',
|
|
89
|
+
streamId: 'src-1',
|
|
90
|
+
sourceWorktree: '/tmp/wt',
|
|
91
|
+
targetStreamId: 'target-1',
|
|
92
|
+
taskRef,
|
|
93
|
+
workspaceManager: ws,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
expect(ws.mergeStream).toHaveBeenCalledWith(
|
|
97
|
+
expect.objectContaining({ metadata: { task_ref: taskRef } })
|
|
98
|
+
);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('omits metadata when ctx.taskRef is absent', async () => {
|
|
102
|
+
const strategy = new MergeToParentStrategy();
|
|
103
|
+
const ws = {
|
|
104
|
+
listStreams: vi.fn(() => []),
|
|
105
|
+
mergeStream: vi.fn(() => ({ success: true, newHead: 'bbb' })),
|
|
106
|
+
} as unknown as WorkspaceManager;
|
|
107
|
+
|
|
108
|
+
await strategy.land({
|
|
109
|
+
agentId: 'agent-1',
|
|
110
|
+
streamId: 'src-1',
|
|
111
|
+
sourceWorktree: '/tmp/wt',
|
|
112
|
+
targetStreamId: 'target-1',
|
|
113
|
+
workspaceManager: ws,
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
expect(ws.mergeStream).toHaveBeenCalledWith(
|
|
117
|
+
expect.objectContaining({ metadata: undefined })
|
|
118
|
+
);
|
|
119
|
+
});
|
|
78
120
|
});
|
|
79
121
|
|
|
80
122
|
describe('QueueToBranchStrategy', () => {
|
|
@@ -81,6 +81,7 @@ export class MergeToParentStrategy implements LandingStrategy {
|
|
|
81
81
|
targetStreamId,
|
|
82
82
|
agentId: ctx.agentId,
|
|
83
83
|
worktree: mergeWorktree.path,
|
|
84
|
+
metadata: ctx.taskRef ? { task_ref: ctx.taskRef } : undefined,
|
|
84
85
|
});
|
|
85
86
|
|
|
86
87
|
// Cascade rebase on dependents if requested.
|
|
@@ -70,7 +70,8 @@ export class SpawnResolverStrategy implements ConflictRecoveryStrategy {
|
|
|
70
70
|
};
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
// Spawn the resolver
|
|
73
|
+
// Spawn the resolver. Injects MACRO_RECOVERY_STRATEGY + MACRO_CONFLICT_ID
|
|
74
|
+
// so the resolve_conflict MCP tool can tag the resolution correctly.
|
|
74
75
|
let resolverAgentId: string;
|
|
75
76
|
try {
|
|
76
77
|
const spawnOpts: SpawnAgentOptions = {
|
|
@@ -78,6 +79,12 @@ export class SpawnResolverStrategy implements ConflictRecoveryStrategy {
|
|
|
78
79
|
task: `Resolve conflict ${ctx.conflictId} on stream ${ctx.streamId}`,
|
|
79
80
|
parent: ctx.landingAgentId,
|
|
80
81
|
capabilities: ['workspace.commit', 'workspace.resolve', 'workspace.read'],
|
|
82
|
+
config: {
|
|
83
|
+
env: {
|
|
84
|
+
MACRO_RECOVERY_STRATEGY: 'spawn-resolver',
|
|
85
|
+
MACRO_CONFLICT_ID: ctx.conflictId,
|
|
86
|
+
},
|
|
87
|
+
},
|
|
81
88
|
};
|
|
82
89
|
const spawned = await this.opts.agentManager.spawn(spawnOpts);
|
|
83
90
|
resolverAgentId = spawned.id;
|
|
@@ -124,6 +124,13 @@ export interface LandingContext {
|
|
|
124
124
|
streamId: StreamId;
|
|
125
125
|
sourceWorktree: string;
|
|
126
126
|
targetStreamId?: StreamId;
|
|
127
|
+
/**
|
|
128
|
+
* Strategy selector. Accepts either an internal strategy name
|
|
129
|
+
* (`merge-to-parent`, `queue-to-branch`, …) or the YAML form
|
|
130
|
+
* (`merge_to_parent_stream`, `queue_to_branch`, …). `WorkspaceManager.land`
|
|
131
|
+
* normalizes. When undefined, `merge-to-parent` is used.
|
|
132
|
+
*/
|
|
133
|
+
strategyName?: string;
|
|
127
134
|
strategyConfig?: Record<string, unknown>;
|
|
128
135
|
/** Reference to the manager; strategies call back for merge/cascade. */
|
|
129
136
|
workspaceManager: unknown; // WorkspaceManager — circular; narrowed at callsite
|
package/src/workspace/types.ts
CHANGED
|
@@ -353,12 +353,17 @@ export interface WorkspaceManager {
|
|
|
353
353
|
|
|
354
354
|
/**
|
|
355
355
|
* Merge a source stream into a target stream.
|
|
356
|
+
*
|
|
357
|
+
* `metadata` is forwarded into the `x-cascade/stream.merged` emit so
|
|
358
|
+
* consumers (e.g., the OpenHive hub) can bind the merge to a task ref.
|
|
359
|
+
* Landing strategies pass `{ task_ref: ctx.taskRef }` through here.
|
|
356
360
|
*/
|
|
357
361
|
mergeStream(opts: {
|
|
358
362
|
sourceStreamId: StreamId;
|
|
359
363
|
targetStreamId: StreamId;
|
|
360
364
|
agentId: import('./types-v3.js').Principal;
|
|
361
365
|
worktree: string;
|
|
366
|
+
metadata?: import('git-cascade/events').EventMetadata;
|
|
362
367
|
}): import('./types-v3.js').MergeResult;
|
|
363
368
|
|
|
364
369
|
/**
|
|
@@ -422,6 +427,21 @@ export interface WorkspaceManager {
|
|
|
422
427
|
*/
|
|
423
428
|
registerLandingStrategy(strategy: import('./types-v3.js').LandingStrategy): void;
|
|
424
429
|
|
|
430
|
+
/**
|
|
431
|
+
* Dispatch a landing. Resolves the strategy by `ctx.strategyName`
|
|
432
|
+
* (defaulting to `merge-to-parent`), accepts both internal and YAML-style
|
|
433
|
+
* names, and invokes the strategy's `land(ctx)`. Strategies call back
|
|
434
|
+
* into this manager via `ctx.workspaceManager`, which is filled in here.
|
|
435
|
+
*
|
|
436
|
+
* Returns the strategy's `MergeResult`. Conflicts are reflected in the
|
|
437
|
+
* result (`success: false` + `conflicts: [...]`); thrown errors indicate
|
|
438
|
+
* unrecoverable failures (unknown strategy, strategy rejected context,
|
|
439
|
+
* transport-level issues).
|
|
440
|
+
*/
|
|
441
|
+
land(
|
|
442
|
+
ctx: import('./types-v3.js').LandingContext,
|
|
443
|
+
): Promise<import('./types-v3.js').MergeResult>;
|
|
444
|
+
|
|
425
445
|
/**
|
|
426
446
|
* Run macro-level reconciliation:
|
|
427
447
|
* - Delegates to git-cascade's `reconcile()` for stream↔git sync.
|
|
@@ -1107,9 +1107,18 @@ export class DefaultWorkspaceManager implements WorkspaceManager {
|
|
|
1107
1107
|
targetStreamId: StreamId;
|
|
1108
1108
|
agentId: import('./types-v3.js').Principal;
|
|
1109
1109
|
worktree: string;
|
|
1110
|
+
/**
|
|
1111
|
+
* Free-form metadata forwarded into the `x-cascade/stream.merged` emit.
|
|
1112
|
+
* The canonical binding is `{ task_ref: { resource_id, node_id } }` —
|
|
1113
|
+
* landing strategies thread `LandingContext.taskRef` through here so the
|
|
1114
|
+
* hub's cascade_merges projection records which task drove the merge.
|
|
1115
|
+
*/
|
|
1116
|
+
metadata?: import('git-cascade/events').EventMetadata;
|
|
1110
1117
|
}): import('./types-v3.js').MergeResult {
|
|
1111
|
-
// git-cascade's MergeStreamOptions uses `sourceStream`/`targetStream
|
|
1112
|
-
//
|
|
1118
|
+
// git-cascade's MergeStreamOptions uses `sourceStream`/`targetStream` and
|
|
1119
|
+
// doesn't accept an opts.metadata field — the tagging is our concern, not
|
|
1120
|
+
// the tracker's. Carry `opts.metadata` through on the emitted event
|
|
1121
|
+
// instead, which is what the hub's cascade_merges projection reads.
|
|
1113
1122
|
const result = this.adapter.mergeStream({
|
|
1114
1123
|
sourceStream: opts.sourceStreamId,
|
|
1115
1124
|
targetStream: opts.targetStreamId,
|
|
@@ -1121,6 +1130,7 @@ export class DefaultWorkspaceManager implements WorkspaceManager {
|
|
|
1121
1130
|
sourceStreamId: opts.sourceStreamId,
|
|
1122
1131
|
targetStreamId: opts.targetStreamId,
|
|
1123
1132
|
mergeCommit: result.newHead,
|
|
1133
|
+
...(opts.metadata ? { metadata: opts.metadata } : {}),
|
|
1124
1134
|
});
|
|
1125
1135
|
} else {
|
|
1126
1136
|
this.emit('stream:conflicted', {
|
|
@@ -1295,6 +1305,31 @@ export class DefaultWorkspaceManager implements WorkspaceManager {
|
|
|
1295
1305
|
this.landingStrategies.set(strategy.name, strategy);
|
|
1296
1306
|
}
|
|
1297
1307
|
|
|
1308
|
+
async land(
|
|
1309
|
+
ctx: import('./types-v3.js').LandingContext,
|
|
1310
|
+
): Promise<import('./types-v3.js').MergeResult> {
|
|
1311
|
+
const internalName = resolveLandingStrategyName(ctx.strategyName);
|
|
1312
|
+
if (internalName === 'none') {
|
|
1313
|
+
return { success: true, alreadyMerged: true } as import('./types-v3.js').MergeResult;
|
|
1314
|
+
}
|
|
1315
|
+
const strategy = this.landingStrategies.get(internalName);
|
|
1316
|
+
if (!strategy) {
|
|
1317
|
+
throw new Error(
|
|
1318
|
+
`No landing strategy registered for "${internalName}" (from ctx.strategyName="${ctx.strategyName ?? 'merge-to-parent'}"). Registered: ${Array.from(this.landingStrategies.keys()).join(', ') || '<none>'}.`,
|
|
1319
|
+
);
|
|
1320
|
+
}
|
|
1321
|
+
const resolved: import('./types-v3.js').LandingContext = {
|
|
1322
|
+
...ctx,
|
|
1323
|
+
workspaceManager: this,
|
|
1324
|
+
};
|
|
1325
|
+
if (strategy.canLand && !strategy.canLand(resolved)) {
|
|
1326
|
+
throw new Error(
|
|
1327
|
+
`Landing strategy "${internalName}" rejected context for agent ${ctx.agentId}, stream ${ctx.streamId}`,
|
|
1328
|
+
);
|
|
1329
|
+
}
|
|
1330
|
+
return strategy.land(resolved);
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1298
1333
|
reconcileV3(): import('./types-v3.js').MacroReconcileResult {
|
|
1299
1334
|
const result: import('./types-v3.js').MacroReconcileResult = {
|
|
1300
1335
|
streamsChecked: 0,
|
|
@@ -1516,3 +1551,27 @@ export function createWorkspaceManagerWithAdapter(
|
|
|
1516
1551
|
): DefaultWorkspaceManager {
|
|
1517
1552
|
return new DefaultWorkspaceManager(adapter, config);
|
|
1518
1553
|
}
|
|
1554
|
+
|
|
1555
|
+
// ═════════════════════════════════════════════════════════════════════════════
|
|
1556
|
+
// Landing strategy name resolution
|
|
1557
|
+
// ═════════════════════════════════════════════════════════════════════════════
|
|
1558
|
+
//
|
|
1559
|
+
// YAML uses snake_case (`merge_to_parent_stream`, `queue_to_branch`, …) to
|
|
1560
|
+
// match the team-config naming convention. Strategy classes expose
|
|
1561
|
+
// kebab-case internal names (`merge-to-parent`, …). `WorkspaceManager.land()`
|
|
1562
|
+
// accepts either and normalizes before dispatch so AgentManagerV2 can pass
|
|
1563
|
+
// `roleConfig.landing` directly without another translation layer.
|
|
1564
|
+
|
|
1565
|
+
const YAML_TO_INTERNAL_LANDING: Record<string, string> = {
|
|
1566
|
+
merge_to_parent_stream: 'merge-to-parent',
|
|
1567
|
+
queue_to_branch: 'queue-to-branch',
|
|
1568
|
+
direct_push: 'direct-push',
|
|
1569
|
+
optimistic_push: 'optimistic-push',
|
|
1570
|
+
cherry_pick_stack: 'cherry-pick-stack',
|
|
1571
|
+
none: 'none',
|
|
1572
|
+
};
|
|
1573
|
+
|
|
1574
|
+
export function resolveLandingStrategyName(input?: string): string {
|
|
1575
|
+
if (!input) return 'merge-to-parent';
|
|
1576
|
+
return YAML_TO_INTERNAL_LANDING[input] ?? input;
|
|
1577
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
name: self-driving
|
|
2
|
+
description: "Cursor-style autonomous codebase development: planners explore and create tasks, grinders claim and execute in their own streams, judges evaluate quality."
|
|
3
|
+
version: 1
|
|
4
|
+
|
|
5
|
+
# ─────────────────────────────────────────────────────────────
|
|
6
|
+
# Roles
|
|
7
|
+
# ─────────────────────────────────────────────────────────────
|
|
8
|
+
roles:
|
|
9
|
+
- planner
|
|
10
|
+
- grinder
|
|
11
|
+
- judge
|
|
12
|
+
|
|
13
|
+
# ─────────────────────────────────────────────────────────────
|
|
14
|
+
# Topology
|
|
15
|
+
# ─────────────────────────────────────────────────────────────
|
|
16
|
+
topology:
|
|
17
|
+
root:
|
|
18
|
+
role: planner
|
|
19
|
+
prompt: prompts/planner.md
|
|
20
|
+
config:
|
|
21
|
+
model: sonnet
|
|
22
|
+
companions:
|
|
23
|
+
- role: judge
|
|
24
|
+
prompt: prompts/judge.md
|
|
25
|
+
config:
|
|
26
|
+
model: haiku
|
|
27
|
+
spawn_rules:
|
|
28
|
+
planner: [grinder, planner]
|
|
29
|
+
judge: []
|
|
30
|
+
grinder: []
|
|
31
|
+
|
|
32
|
+
# ─────────────────────────────────────────────────────────────
|
|
33
|
+
# Communication
|
|
34
|
+
# ─────────────────────────────────────────────────────────────
|
|
35
|
+
communication:
|
|
36
|
+
enforcement: permissive
|
|
37
|
+
|
|
38
|
+
channels:
|
|
39
|
+
task_updates:
|
|
40
|
+
description: "Task lifecycle events"
|
|
41
|
+
signals: [TASK_CREATED, TASK_COMPLETED, TASK_FAILED]
|
|
42
|
+
work_coordination:
|
|
43
|
+
description: "Work assignment and completion"
|
|
44
|
+
signals: [WORK_ASSIGNED, WORKER_DONE, MERGE_REQUEST]
|
|
45
|
+
health:
|
|
46
|
+
description: "System health monitoring"
|
|
47
|
+
signals: [HEALTH_CHECK, METRIC_SNAPSHOT, GREEN_SNAPSHOT, FIXUP_CREATED]
|
|
48
|
+
|
|
49
|
+
subscriptions:
|
|
50
|
+
planner:
|
|
51
|
+
- channel: task_updates
|
|
52
|
+
- channel: work_coordination
|
|
53
|
+
signals: [WORKER_DONE]
|
|
54
|
+
- channel: health
|
|
55
|
+
signals: [METRIC_SNAPSHOT, GREEN_SNAPSHOT, FIXUP_CREATED]
|
|
56
|
+
judge:
|
|
57
|
+
- channel: task_updates
|
|
58
|
+
signals: [TASK_FAILED]
|
|
59
|
+
- channel: work_coordination
|
|
60
|
+
signals: [WORKER_DONE]
|
|
61
|
+
- channel: health
|
|
62
|
+
grinder:
|
|
63
|
+
- channel: work_coordination
|
|
64
|
+
signals: [WORK_ASSIGNED]
|
|
65
|
+
|
|
66
|
+
emissions:
|
|
67
|
+
planner: [TASK_CREATED, WORK_ASSIGNED, PLANNING_COMPLETE]
|
|
68
|
+
judge: [HEALTH_CHECK, GREEN_SNAPSHOT, FIXUP_CREATED]
|
|
69
|
+
grinder: [WORKER_DONE]
|
|
70
|
+
|
|
71
|
+
routing:
|
|
72
|
+
peers:
|
|
73
|
+
- from: judge
|
|
74
|
+
to: planner
|
|
75
|
+
via: direct
|
|
76
|
+
signals: [FIXUP_CREATED, GREEN_SNAPSHOT]
|
|
77
|
+
- from: planner
|
|
78
|
+
to: judge
|
|
79
|
+
via: direct
|
|
80
|
+
signals: [CONVERGENCE_CHECK]
|
|
81
|
+
|
|
82
|
+
# ─────────────────────────────────────────────────────────────
|
|
83
|
+
# macro-agent specific extensions
|
|
84
|
+
# ─────────────────────────────────────────────────────────────
|
|
85
|
+
macro_agent:
|
|
86
|
+
# V3 stream-first workspace topology.
|
|
87
|
+
# Compiled by YamlDrivenTopology into per-spawn WorkspaceDecision values.
|
|
88
|
+
workspace:
|
|
89
|
+
default_stream:
|
|
90
|
+
fork_from: main
|
|
91
|
+
name_template: "{team}"
|
|
92
|
+
change_id_tracking: true
|
|
93
|
+
|
|
94
|
+
on_team_complete: keep
|
|
95
|
+
|
|
96
|
+
roles:
|
|
97
|
+
# Planner shares the team root stream — continuous exploration lives on the
|
|
98
|
+
# same branch as the team's accumulated work; no per-planner fork.
|
|
99
|
+
planner:
|
|
100
|
+
workspace: attach_to_team_root
|
|
101
|
+
capabilities:
|
|
102
|
+
- workspace.read
|
|
103
|
+
- agent.spawn
|
|
104
|
+
|
|
105
|
+
# Grinders fork their own stream off the team root, land via direct-push
|
|
106
|
+
# (trunk integration). A conflict during landing aborts and leaves the
|
|
107
|
+
# stream for human / judge review.
|
|
108
|
+
grinder:
|
|
109
|
+
workspace: new_stream
|
|
110
|
+
stream_lineage: fork_from_team_root
|
|
111
|
+
landing: direct_push
|
|
112
|
+
on_conflict: defer
|
|
113
|
+
capabilities:
|
|
114
|
+
- workspace.commit
|
|
115
|
+
- workspace.land
|
|
116
|
+
|
|
117
|
+
# Judge is read-only — it observes repo state but doesn't need a
|
|
118
|
+
# workspace of its own.
|
|
119
|
+
judge:
|
|
120
|
+
workspace: none
|
|
121
|
+
capabilities:
|
|
122
|
+
- workspace.read
|
|
123
|
+
|
|
124
|
+
# Declarative shorthand read by TeamRuntimeV2.getStrategyName(). `trunk`
|
|
125
|
+
# pairs with the grinder's direct_push landing above: every task lands
|
|
126
|
+
# straight onto the team-root stream rather than going through a merge
|
|
127
|
+
# queue. Kept here as a top-level scalar so runtimes that don't parse the
|
|
128
|
+
# full V3 workspace block (env-var consumers, logs, metrics labels) still
|
|
129
|
+
# see the integration strategy.
|
|
130
|
+
integration:
|
|
131
|
+
strategy: trunk
|
|
132
|
+
|
|
133
|
+
task_assignment:
|
|
134
|
+
mode: pull
|
|
135
|
+
pull:
|
|
136
|
+
idle_timeout_s: 300
|
|
137
|
+
claim_retry_delay_ms: 2000
|
|
138
|
+
max_concurrent_per_agent: 1
|
|
139
|
+
|
|
140
|
+
observability:
|
|
141
|
+
metrics_window_s: 3600
|
|
142
|
+
snapshot_interval_s: 300
|
package/tsconfig.json
CHANGED
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"declaration": true,
|
|
14
14
|
"declarationMap": true,
|
|
15
15
|
"sourceMap": true,
|
|
16
|
-
"resolveJsonModule": true
|
|
16
|
+
"resolveJsonModule": true,
|
|
17
|
+
"types": ["node", "better-sqlite3", "express", "js-yaml", "supertest", "ws"]
|
|
17
18
|
},
|
|
18
19
|
"include": ["src/**/*"],
|
|
19
20
|
"exclude": ["node_modules", "dist", "**/*.test.ts"]
|