opencode-manifold 0.5.7 → 0.5.8
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/dist/index.js +214 -334
- package/package.json +1 -1
- package/src/templates/agents/clerk.md +17 -337
- package/src/templates/agents/manifold.md +17 -2
- package/src/templates/agents/senior-dev.md +36 -33
- package/src/templates/agents/todo.md +14 -0
- package/src/templates/manifold/settings.json +1 -1
- package/src/templates/skills/research/SKILL.md +75 -0
package/dist/index.js
CHANGED
|
@@ -320,342 +320,206 @@ function extractTaskFromPlan(planContent, taskNumber) {
|
|
|
320
320
|
}
|
|
321
321
|
return null;
|
|
322
322
|
}
|
|
323
|
-
function runDispatcherLogic(args, state, settings) {
|
|
324
|
-
const
|
|
325
|
-
const taskNumber = args.task_number || (state?.task_number || 0);
|
|
326
|
-
const planFile = args.plan_file || (state?.plan_file || "");
|
|
323
|
+
function runDispatcherLogic(args, state, settings, taskDescription) {
|
|
324
|
+
const taskNumber = args.task_number || state?.task_number || 0;
|
|
327
325
|
const slug = state?.slug || "";
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
currentState = {
|
|
326
|
+
if (!state || state.phase === "init" || state.phase === "complete" || state.phase === "escalated") {
|
|
327
|
+
const newState = {
|
|
331
328
|
task_number: taskNumber,
|
|
332
|
-
plan_file:
|
|
329
|
+
plan_file: args.plan_file || state?.plan_file || "",
|
|
333
330
|
slug,
|
|
331
|
+
phase: "awaiting_execution",
|
|
332
|
+
senior_output: "",
|
|
333
|
+
clerk_summary: "",
|
|
334
334
|
loops: 0,
|
|
335
|
-
|
|
336
|
-
researchSummary: "",
|
|
337
|
-
implementationOutput: "",
|
|
338
|
-
reviewFeedback: "",
|
|
339
|
-
debugAnalysis: ""
|
|
335
|
+
clerk_retries: 0
|
|
340
336
|
};
|
|
341
|
-
} else {
|
|
342
|
-
currentState = { ...state };
|
|
343
|
-
}
|
|
344
|
-
if (args.researchSummary)
|
|
345
|
-
currentState.researchSummary = args.researchSummary;
|
|
346
|
-
if (args.implementationOutput)
|
|
347
|
-
currentState.implementationOutput = args.implementationOutput;
|
|
348
|
-
if (args.reviewFeedback)
|
|
349
|
-
currentState.reviewFeedback = args.reviewFeedback;
|
|
350
|
-
if (args.debugAnalysis)
|
|
351
|
-
currentState.debugAnalysis = args.debugAnalysis;
|
|
352
|
-
if (isNewTask) {
|
|
353
337
|
return {
|
|
354
|
-
route: "
|
|
338
|
+
route: "execute",
|
|
355
339
|
agent: "clerk",
|
|
356
|
-
prompt:
|
|
357
|
-
state: {
|
|
358
|
-
task_id: `${currentState.slug}-${currentState.task_number.toString().padStart(3, "0")}`,
|
|
359
|
-
loops: 0,
|
|
360
|
-
maxLoops: settings.maxLoops,
|
|
361
|
-
clerkRetries: 0
|
|
362
|
-
},
|
|
363
|
-
message: "Researching codebase and wiki context"
|
|
364
|
-
};
|
|
365
|
-
}
|
|
366
|
-
if (args.researchComplete === true && !args.hasImplementation) {
|
|
367
|
-
return {
|
|
368
|
-
route: "implement",
|
|
369
|
-
agent: "senior-dev",
|
|
370
|
-
prompt: buildScopedPrompt(currentState.researchSummary, args),
|
|
371
|
-
state: {
|
|
372
|
-
task_id: `${currentState.slug}-${currentState.task_number.toString().padStart(3, "0")}`,
|
|
373
|
-
loops: 0,
|
|
374
|
-
maxLoops: settings.maxLoops,
|
|
375
|
-
clerkRetries: 0
|
|
376
|
-
},
|
|
377
|
-
message: "Sending to senior-dev for implementation"
|
|
378
|
-
};
|
|
379
|
-
}
|
|
380
|
-
if (args.hasImplementation === true && args.reviewDone === false) {
|
|
381
|
-
return {
|
|
382
|
-
route: "review",
|
|
383
|
-
agent: "junior-dev",
|
|
384
|
-
prompt: buildReviewPrompt(currentState.implementationOutput, args),
|
|
340
|
+
prompt: buildExecutePrompt(taskNumber, taskDescription),
|
|
385
341
|
state: {
|
|
386
|
-
task_id: `${
|
|
387
|
-
|
|
388
|
-
maxLoops: settings.maxLoops,
|
|
389
|
-
clerkRetries: 0
|
|
342
|
+
task_id: `${slug}-${taskNumber.toString().padStart(3, "0")}`,
|
|
343
|
+
phase: "awaiting_execution"
|
|
390
344
|
},
|
|
391
|
-
message: "
|
|
345
|
+
message: "Ready to execute task"
|
|
392
346
|
};
|
|
393
347
|
}
|
|
394
|
-
if (
|
|
348
|
+
if (state.phase === "awaiting_execution") {
|
|
395
349
|
return {
|
|
396
|
-
route: "
|
|
350
|
+
route: "outcome_check",
|
|
397
351
|
agent: "clerk",
|
|
398
|
-
prompt:
|
|
352
|
+
prompt: buildOutcomeCheckPrompt(),
|
|
399
353
|
state: {
|
|
400
|
-
task_id: `${
|
|
401
|
-
|
|
402
|
-
maxLoops: settings.maxLoops,
|
|
403
|
-
clerkRetries: currentState.clerkRetries
|
|
354
|
+
task_id: `${slug}-${taskNumber.toString().padStart(3, "0")}`,
|
|
355
|
+
phase: "awaiting_outcome"
|
|
404
356
|
},
|
|
405
|
-
message: "
|
|
357
|
+
message: "Waiting for senior dev outcome"
|
|
406
358
|
};
|
|
407
359
|
}
|
|
408
|
-
if (
|
|
409
|
-
|
|
410
|
-
if (
|
|
411
|
-
|
|
360
|
+
if (state.phase === "awaiting_outcome") {
|
|
361
|
+
const isSuccess = args.success === true;
|
|
362
|
+
if (isSuccess) {
|
|
363
|
+
return {
|
|
364
|
+
route: "logging",
|
|
365
|
+
agent: "clerk",
|
|
366
|
+
prompt: buildLoggingPrompt(state, taskDescription),
|
|
367
|
+
state: {
|
|
368
|
+
task_id: `${slug}-${taskNumber.toString().padStart(3, "0")}`,
|
|
369
|
+
phase: "logging"
|
|
370
|
+
},
|
|
371
|
+
message: "Task succeeded - logging results"
|
|
372
|
+
};
|
|
373
|
+
} else {
|
|
374
|
+
if (state.clerk_retries < settings.maxRetries) {
|
|
412
375
|
return {
|
|
413
|
-
route: "
|
|
414
|
-
agent: "
|
|
415
|
-
prompt:
|
|
376
|
+
route: "reprompt",
|
|
377
|
+
agent: "clerk",
|
|
378
|
+
prompt: buildRePromptPrompt(state, taskDescription),
|
|
416
379
|
state: {
|
|
417
|
-
task_id: `${
|
|
418
|
-
|
|
419
|
-
maxLoops: settings.maxLoops,
|
|
420
|
-
clerkRetries: 0
|
|
380
|
+
task_id: `${slug}-${taskNumber.toString().padStart(3, "0")}`,
|
|
381
|
+
phase: "awaiting_execution"
|
|
421
382
|
},
|
|
422
|
-
message: `
|
|
383
|
+
message: `Retrying task (attempt ${state.clerk_retries + 1}/${settings.maxRetries})`
|
|
423
384
|
};
|
|
424
|
-
}
|
|
425
|
-
if (args.debugComplete === true && settings.clerkRetryEnabled && currentState.clerkRetries === 0) {
|
|
426
|
-
currentState.clerkRetries = 1;
|
|
427
|
-
currentState.loops = 0;
|
|
385
|
+
} else {
|
|
428
386
|
return {
|
|
429
|
-
route: "
|
|
430
|
-
agent:
|
|
431
|
-
prompt:
|
|
387
|
+
route: "escalate",
|
|
388
|
+
agent: null,
|
|
389
|
+
prompt: buildEscalationPrompt(state, taskDescription),
|
|
432
390
|
state: {
|
|
433
|
-
task_id: `${
|
|
434
|
-
|
|
435
|
-
maxLoops: settings.maxLoops,
|
|
436
|
-
clerkRetries: 1
|
|
391
|
+
task_id: `${slug}-${taskNumber.toString().padStart(3, "0")}`,
|
|
392
|
+
phase: "escalated"
|
|
437
393
|
},
|
|
438
|
-
message: "
|
|
394
|
+
message: "Escalating to user - all retries exhausted"
|
|
439
395
|
};
|
|
440
396
|
}
|
|
441
|
-
return {
|
|
442
|
-
route: "escalate_user",
|
|
443
|
-
agent: null,
|
|
444
|
-
prompt: `Task ${taskNumber} has exhausted all loops (${settings.maxLoops}) and debug analysis. Last feedback: ${currentState.reviewFeedback}`,
|
|
445
|
-
state: {
|
|
446
|
-
task_id: `${currentState.slug}-${currentState.task_number.toString().padStart(3, "0")}`,
|
|
447
|
-
loops: currentState.loops,
|
|
448
|
-
maxLoops: settings.maxLoops,
|
|
449
|
-
clerkRetries: currentState.clerkRetries
|
|
450
|
-
},
|
|
451
|
-
message: "ESCALATING TO USER - all loops exhausted"
|
|
452
|
-
};
|
|
453
397
|
}
|
|
454
|
-
return {
|
|
455
|
-
route: "re-implement",
|
|
456
|
-
agent: "senior-dev",
|
|
457
|
-
prompt: buildReImplementPrompt(currentState, args),
|
|
458
|
-
state: {
|
|
459
|
-
task_id: `${currentState.slug}-${currentState.task_number.toString().padStart(3, "0")}`,
|
|
460
|
-
loops: currentState.loops,
|
|
461
|
-
maxLoops: settings.maxLoops,
|
|
462
|
-
clerkRetries: currentState.clerkRetries
|
|
463
|
-
},
|
|
464
|
-
message: `Loop ${currentState.loops}/${settings.maxLoops} - re-implementing with junior feedback`
|
|
465
|
-
};
|
|
466
|
-
}
|
|
467
|
-
if (args.debugComplete === true && args.reResearched === false) {
|
|
468
|
-
return {
|
|
469
|
-
route: "re-implement",
|
|
470
|
-
agent: "senior-dev",
|
|
471
|
-
prompt: buildDebugImplementPrompt(currentState, args),
|
|
472
|
-
state: {
|
|
473
|
-
task_id: `${currentState.slug}-${currentState.task_number.toString().padStart(3, "0")}`,
|
|
474
|
-
loops: currentState.loops,
|
|
475
|
-
maxLoops: settings.maxLoops,
|
|
476
|
-
clerkRetries: currentState.clerkRetries
|
|
477
|
-
},
|
|
478
|
-
message: "Re-implementing with debug suggestion"
|
|
479
|
-
};
|
|
480
|
-
}
|
|
481
|
-
if (args.reResearched === true) {
|
|
482
|
-
currentState.loops = 0;
|
|
483
|
-
return {
|
|
484
|
-
route: "implement",
|
|
485
|
-
agent: "senior-dev",
|
|
486
|
-
prompt: buildScopedPrompt(currentState.researchSummary, args),
|
|
487
|
-
state: {
|
|
488
|
-
task_id: `${currentState.slug}-${currentState.task_number.toString().padStart(3, "0")}`,
|
|
489
|
-
loops: 0,
|
|
490
|
-
maxLoops: settings.maxLoops,
|
|
491
|
-
clerkRetries: currentState.clerkRetries
|
|
492
|
-
},
|
|
493
|
-
message: "Starting fresh loop with new research"
|
|
494
|
-
};
|
|
495
398
|
}
|
|
496
399
|
return {
|
|
497
|
-
route: "
|
|
400
|
+
route: "escalate",
|
|
498
401
|
agent: null,
|
|
499
|
-
prompt: "Dispatcher encountered
|
|
402
|
+
prompt: "Dispatcher encountered unexpected state",
|
|
500
403
|
state: {
|
|
501
|
-
task_id: `${
|
|
502
|
-
|
|
503
|
-
maxLoops: settings.maxLoops,
|
|
504
|
-
clerkRetries: currentState.clerkRetries
|
|
404
|
+
task_id: `${slug}-${taskNumber.toString().padStart(3, "0")}`,
|
|
405
|
+
phase: "escalated"
|
|
505
406
|
},
|
|
506
|
-
message: "
|
|
407
|
+
message: "Unexpected state - escalating"
|
|
507
408
|
};
|
|
508
409
|
}
|
|
509
|
-
function
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
1.
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
-
|
|
523
|
-
-
|
|
524
|
-
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
410
|
+
function buildExecutePrompt(taskNumber, taskDescription) {
|
|
411
|
+
return `CLERK - EXECUTE TASK
|
|
412
|
+
TASK NUMBER: ${taskNumber}
|
|
413
|
+
TASK: ${taskDescription}
|
|
414
|
+
|
|
415
|
+
INSTRUCTIONS:
|
|
416
|
+
|
|
417
|
+
1. RESEARCH
|
|
418
|
+
Use the Research skill with the given task to gather potentially relevant context.
|
|
419
|
+
|
|
420
|
+
2. COMPOSE SCOPED PROMPT
|
|
421
|
+
Combine into a scoped prompt:
|
|
422
|
+
- Task goal (what Senior Dev must accomplish)
|
|
423
|
+
- Relevant code snippets from research (3-10, include file paths)
|
|
424
|
+
- Prior decisions from wiki logs
|
|
425
|
+
- Design guidelines (language/framework conventions, patterns)
|
|
426
|
+
Balance: enough to be useful, not overwhelming. Target ~800 words max.
|
|
427
|
+
|
|
428
|
+
3. APPLY FRAMING
|
|
429
|
+
- Prefer "what data goes in and what comes out" framing when it makes the goal clearer
|
|
430
|
+
- If task has purity tag ([pure], [shell], [mixed]):
|
|
431
|
+
- [pure]: Frame as data transformation, specify input/output types, emphasize no IO/side effects
|
|
432
|
+
- [shell]: Clarify IO boundary, what external system involved
|
|
433
|
+
- [mixed]: Note where logic/IO boundary falls
|
|
434
|
+
- Don't force functional style if task is naturally imperative
|
|
435
|
+
|
|
436
|
+
4. CREATE TASK LOG
|
|
437
|
+
Write initial entry to \`Manifold/tasks/<slug>-<task-number>.md\` (e.g., auth-fix-001.md):
|
|
438
|
+
- Header: Date, Status=IN_PROGRESS, Task Description
|
|
439
|
+
- Include the scoped prompt you composed
|
|
440
|
+
- List context documents used (files, wiki logs, graphs)
|
|
441
|
+
|
|
442
|
+
5. CALL SENIOR-DEV
|
|
443
|
+
Call @senior-dev with the finalized scoped prompt. Wait for response.
|
|
444
|
+
|
|
445
|
+
6. REPORT OUTCOME
|
|
446
|
+
When senior-dev returns, determine if it reported "task complete" or "task failure".
|
|
447
|
+
Call dispatchTask() again (no arguments needed - the tool will ask for the result next).
|
|
448
|
+
|
|
449
|
+
CONSTRAINTS:
|
|
450
|
+
- Do not make autonomous decisions about the task lifecycle.
|
|
451
|
+
- Wait for the dispatcher's next instruction after senior-dev completes.`;
|
|
535
452
|
}
|
|
536
|
-
function
|
|
537
|
-
return `
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
}
|
|
546
|
-
function buildReviewPrompt(implementation, args) {
|
|
547
|
-
return `You are the Junior Developer reviewing the Senior Developer's implementation.
|
|
548
|
-
|
|
549
|
-
Task: ${args.description}
|
|
550
|
-
|
|
551
|
-
Senior Developer's Implementation:
|
|
552
|
-
${implementation}
|
|
553
|
-
|
|
554
|
-
Review the implementation against the task requirements. Your response MUST begin with exactly "COMPLETE" or "QUESTIONS" as the first word.
|
|
555
|
-
|
|
556
|
-
If COMPLETE: Briefly explain why the implementation is acceptable.
|
|
557
|
-
If QUESTIONS: List specific issues blocking approval with actionable feedback.`;
|
|
558
|
-
}
|
|
559
|
-
function buildReImplementPrompt(state, args) {
|
|
560
|
-
return `You are the Senior Developer. Re-implement this task addressing the Junior Developer's feedback.
|
|
561
|
-
|
|
562
|
-
Task: ${args.description}
|
|
563
|
-
|
|
564
|
-
Original Scoped Prompt:
|
|
565
|
-
${state.researchSummary}
|
|
566
|
-
|
|
567
|
-
Junior Developer's Feedback:
|
|
568
|
-
${state.reviewFeedback}
|
|
569
|
-
|
|
570
|
-
Address these issues and resubmit your implementation.`;
|
|
571
|
-
}
|
|
572
|
-
function buildDebugPrompt(state, args) {
|
|
573
|
-
return `You are the Debug Agent. The Senior/Junior loop has failed ${state.loops} times.
|
|
574
|
-
|
|
575
|
-
Task: ${args.description}
|
|
576
|
-
|
|
577
|
-
Research Context:
|
|
578
|
-
${state.researchSummary}
|
|
579
|
-
|
|
580
|
-
Failed Implementation:
|
|
581
|
-
${state.implementationOutput}
|
|
582
|
-
|
|
583
|
-
Junior Developer's Feedback:
|
|
584
|
-
${state.reviewFeedback}
|
|
585
|
-
|
|
586
|
-
Analyze why the loop is stuck and suggest a concrete alternative approach.`;
|
|
587
|
-
}
|
|
588
|
-
function buildDebugImplementPrompt(state, args) {
|
|
589
|
-
return `You are the Senior Developer. Implement the Debug Agent's suggestion.
|
|
590
|
-
|
|
591
|
-
Task: ${args.description}
|
|
592
|
-
|
|
593
|
-
Debug Agent's Analysis:
|
|
594
|
-
${state.debugAnalysis}
|
|
595
|
-
|
|
596
|
-
Implement the task following the Debug agent's suggestion.`;
|
|
453
|
+
function buildOutcomeCheckPrompt() {
|
|
454
|
+
return `CLERK - OUTCOME CHECK
|
|
455
|
+
INSTRUCTIONS:
|
|
456
|
+
1. Based on the senior-dev's response you just received, determine the outcome:
|
|
457
|
+
- If senior-dev said "task complete" (or similar), pass \`success: true\` on your next dispatchTask call
|
|
458
|
+
- If senior-dev said "task failure" (or similar), pass \`success: false\` on your next dispatchTask call
|
|
459
|
+
|
|
460
|
+
NEXT CALL:
|
|
461
|
+
Call dispatchTask({ success: true }) or dispatchTask({ success: false }) based on the outcome.`;
|
|
597
462
|
}
|
|
598
|
-
function
|
|
599
|
-
return `You are the Clerk. The previous implementation attempt failed. Re-research with failure context.
|
|
600
|
-
|
|
601
|
-
Original Task: ${args.description}
|
|
602
|
-
|
|
603
|
-
Previous Implementation (failed):
|
|
604
|
-
${state.implementationOutput}
|
|
605
|
-
|
|
606
|
-
Junior Developer's Feedback:
|
|
607
|
-
${state.reviewFeedback}
|
|
608
|
-
|
|
609
|
-
Debug Agent's Suggestion (also didn't work):
|
|
610
|
-
${state.debugAnalysis}
|
|
611
|
-
|
|
612
|
-
Re-research the task with this failure context and compose a new scoped prompt that addresses the underlying issues.`;
|
|
613
|
-
}
|
|
614
|
-
function buildLoggingPrompt(state, args) {
|
|
463
|
+
function buildLoggingPrompt(state, taskDescription) {
|
|
615
464
|
const taskId = `${state.slug}-${state.task_number.toString().padStart(3, "0")}`;
|
|
616
465
|
const date = new Date().toISOString().split("T")[0];
|
|
617
|
-
return `
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
${
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
${
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
-
|
|
638
|
-
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
466
|
+
return `CLERK - LOGGING PHASE
|
|
467
|
+
TASK: ${taskDescription}
|
|
468
|
+
TASK ID: ${taskId}
|
|
469
|
+
|
|
470
|
+
INSTRUCTIONS:
|
|
471
|
+
1. Update task log at \`Manifold/tasks/${taskId}.md\`:
|
|
472
|
+
- Change Status from IN_PROGRESS to COMPLETED (or FAILED if applicable)
|
|
473
|
+
- Add senior-dev's final implementation summary
|
|
474
|
+
- Document what was done and files changed
|
|
475
|
+
- If failed: document what was tried and why it failed
|
|
476
|
+
|
|
477
|
+
2. Update index at \`Manifold/index.md\`:
|
|
478
|
+
- Add: \`- [[${taskId}]] — ${taskDescription} | ${date} | COMPLETED\`
|
|
479
|
+
|
|
480
|
+
3. Append to log at \`Manifold/log.md\`:
|
|
481
|
+
- Add: \`## [${date}] ${taskId} | ${taskDescription} | COMPLETED\`
|
|
482
|
+
|
|
483
|
+
4. Update graph files for touched files:
|
|
484
|
+
- For each file touched, update/add \`Manifold/graph/<graph-name>.md\`
|
|
485
|
+
- Add task ID to "Tasks That Edited" section
|
|
486
|
+
- Replace \`/\` with \`__SL__\` and \`.\` with \`__DT__\` in filenames
|
|
487
|
+
- Example: \`src/middleware/auth.ts\` → \`Manifold/graph/src__SL__middleware__SL__auth__DT__ts.md\`
|
|
488
|
+
|
|
489
|
+
AFTER COMPLETING LOGGING:
|
|
490
|
+
Call dispatchTask() with no arguments. The dispatcher will complete the task and reset state.`;
|
|
491
|
+
}
|
|
492
|
+
function buildRePromptPrompt(state, taskDescription) {
|
|
493
|
+
const attemptNumber = state.clerk_retries + 1;
|
|
494
|
+
return `CLERK - RECOVERY ATTEMPT ${attemptNumber}
|
|
495
|
+
TASK: ${taskDescription}
|
|
496
|
+
PREVIOUS ATTEMPT FAILED
|
|
497
|
+
|
|
498
|
+
INSTRUCTIONS:
|
|
499
|
+
1. Call @senior-dev again with the same task description
|
|
500
|
+
2. Include context from the previous failure:
|
|
501
|
+
- The previous implementation was not accepted
|
|
502
|
+
- Senior-dev should try a different approach
|
|
503
|
+
3. Senior-dev will again manage the review loop internally
|
|
504
|
+
|
|
505
|
+
NEXT:
|
|
506
|
+
After senior-dev completes, call dispatchTask() again to report outcome.`;
|
|
507
|
+
}
|
|
508
|
+
function buildEscalationPrompt(state, taskDescription) {
|
|
509
|
+
return `CLERK - ESCALATION
|
|
510
|
+
TASK: ${taskDescription}
|
|
646
511
|
|
|
647
|
-
|
|
648
|
-
\`## [${date}] ${taskId} | ${args.description} | COMPLETED | ${state.loops} loops\`
|
|
512
|
+
The task has failed after ${state.clerk_retries} recovery attempts.
|
|
649
513
|
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
-
|
|
654
|
-
-
|
|
655
|
-
-
|
|
656
|
-
-
|
|
514
|
+
INSTRUCTIONS:
|
|
515
|
+
1. Log the failure to \`Manifold/tasks/<task-id>.md\` with status=FAILED
|
|
516
|
+
2. Report to the user:
|
|
517
|
+
- Task description: ${taskDescription}
|
|
518
|
+
- Status: FAILED
|
|
519
|
+
- Attempts made: ${state.clerk_retries}
|
|
520
|
+
- Summary of what was tried and why it failed
|
|
657
521
|
|
|
658
|
-
|
|
522
|
+
This task cannot be completed automatically. Human intervention required.`;
|
|
659
523
|
}
|
|
660
524
|
function getClient() {
|
|
661
525
|
if (!pluginClient) {
|
|
@@ -664,44 +528,38 @@ function getClient() {
|
|
|
664
528
|
return pluginClient;
|
|
665
529
|
}
|
|
666
530
|
var dispatchTaskTool = tool({
|
|
667
|
-
description: "Dispatcher for the multi-agent development system. Returns routing instructions based on
|
|
531
|
+
description: "Dispatcher for the multi-agent development system. Returns routing instructions based on task state. Clerk calls this with no arguments to get next prompt.",
|
|
668
532
|
args: {
|
|
669
|
-
task_number: tool.schema.number().optional().describe("
|
|
670
|
-
plan_file: tool.schema.string().optional().describe("Path to
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
reviewPassed: tool.schema.boolean().optional().describe("TRUE: Junior-dev responded with COMPLETE"),
|
|
676
|
-
needsDecomposition: tool.schema.boolean().optional().describe("TRUE: Task requires project-wide decomposition"),
|
|
677
|
-
debugComplete: tool.schema.boolean().optional().describe("TRUE: Debug agent has finished analyzing"),
|
|
678
|
-
reResearched: tool.schema.boolean().optional().describe("TRUE: Clerk has re-researched with failure context"),
|
|
679
|
-
researchSummary: tool.schema.string().optional().describe("Clerk's research findings"),
|
|
680
|
-
implementationOutput: tool.schema.string().optional().describe("Senior-dev's full output"),
|
|
681
|
-
reviewFeedback: tool.schema.string().optional().describe("Junior-dev's full response"),
|
|
682
|
-
debugAnalysis: tool.schema.string().optional().describe("Debug agent's full analysis"),
|
|
683
|
-
notes: tool.schema.string().optional().describe("Optional free-text reasoning")
|
|
533
|
+
task_number: tool.schema.number().optional().describe("Task number"),
|
|
534
|
+
plan_file: tool.schema.string().optional().describe("Path to plan document"),
|
|
535
|
+
description: tool.schema.string().optional().describe("Task description"),
|
|
536
|
+
success: tool.schema.boolean().optional().describe("TRUE if senior-dev completed task successfully, FALSE if failed"),
|
|
537
|
+
senior_output: tool.schema.string().optional().describe("Senior dev's output/summary"),
|
|
538
|
+
clerk_summary: tool.schema.string().optional().describe("Clerk's summary of the task")
|
|
684
539
|
},
|
|
685
540
|
async execute(args, context) {
|
|
686
|
-
const { task_number, plan_file } = args;
|
|
541
|
+
const { task_number, plan_file, description } = args;
|
|
687
542
|
const client = getClient();
|
|
688
543
|
const directory = context.directory;
|
|
689
544
|
await client.app.log({
|
|
690
545
|
body: {
|
|
691
546
|
service: "opencode-manifold",
|
|
692
547
|
level: "info",
|
|
693
|
-
message: `dispatchTask called: task ${task_number || "unknown"}
|
|
548
|
+
message: `dispatchTask called: task ${task_number || "unknown"}`
|
|
694
549
|
}
|
|
695
550
|
});
|
|
696
551
|
const settings = await readSettings(directory);
|
|
697
552
|
const existingState = task_number ? await readDispatcherState(directory, task_number) : null;
|
|
698
|
-
let
|
|
699
|
-
if (args.
|
|
553
|
+
let taskDescription = description || "";
|
|
554
|
+
if (!taskDescription && args.plan_file && task_number) {
|
|
700
555
|
try {
|
|
701
|
-
const planPath = join2(directory, plan_file);
|
|
556
|
+
const planPath = join2(directory, args.plan_file);
|
|
702
557
|
if (existsSync2(planPath)) {
|
|
703
558
|
const planContent = await readFile2(planPath, "utf-8");
|
|
704
|
-
taskInfo = extractTaskFromPlan(planContent, task_number);
|
|
559
|
+
const taskInfo = extractTaskFromPlan(planContent, task_number);
|
|
560
|
+
if (taskInfo) {
|
|
561
|
+
taskDescription = taskInfo.description;
|
|
562
|
+
}
|
|
705
563
|
}
|
|
706
564
|
} catch (error) {
|
|
707
565
|
await client.app.log({
|
|
@@ -713,24 +571,46 @@ var dispatchTaskTool = tool({
|
|
|
713
571
|
});
|
|
714
572
|
}
|
|
715
573
|
}
|
|
716
|
-
const
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
574
|
+
const result = runDispatcherLogic(args, existingState, settings, taskDescription);
|
|
575
|
+
let newPhase = "init";
|
|
576
|
+
if (result.route === "execute")
|
|
577
|
+
newPhase = "awaiting_execution";
|
|
578
|
+
else if (result.route === "outcome_check")
|
|
579
|
+
newPhase = "awaiting_outcome";
|
|
580
|
+
else if (result.route === "logging")
|
|
581
|
+
newPhase = "logging";
|
|
582
|
+
else if (result.route === "complete")
|
|
583
|
+
newPhase = "complete";
|
|
584
|
+
else if (result.route === "escalate")
|
|
585
|
+
newPhase = "escalated";
|
|
586
|
+
else if (result.route === "reprompt")
|
|
587
|
+
newPhase = "awaiting_execution";
|
|
721
588
|
if (task_number && result.state.task_id) {
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
589
|
+
if (result.route === "logging" || result.route === "escalate") {
|
|
590
|
+
const newState = {
|
|
591
|
+
task_number,
|
|
592
|
+
plan_file: plan_file || "",
|
|
593
|
+
slug: result.state.task_id.split("-")[0],
|
|
594
|
+
phase: newPhase,
|
|
595
|
+
senior_output: args.senior_output || existingState?.senior_output || "",
|
|
596
|
+
clerk_summary: args.clerk_summary || existingState?.clerk_summary || "",
|
|
597
|
+
loops: existingState?.loops || 0,
|
|
598
|
+
clerk_retries: existingState?.clerk_retries || 0
|
|
599
|
+
};
|
|
600
|
+
await writeDispatcherState(directory, newState);
|
|
601
|
+
} else {
|
|
602
|
+
const newState = {
|
|
603
|
+
task_number,
|
|
604
|
+
plan_file: plan_file || "",
|
|
605
|
+
slug: result.state.task_id.split("-")[0],
|
|
606
|
+
phase: newPhase,
|
|
607
|
+
senior_output: args.senior_output || existingState?.senior_output || "",
|
|
608
|
+
clerk_summary: args.clerk_summary || existingState?.clerk_summary || "",
|
|
609
|
+
loops: existingState?.loops || 0,
|
|
610
|
+
clerk_retries: existingState?.clerk_retries || 0
|
|
611
|
+
};
|
|
612
|
+
await writeDispatcherState(directory, newState);
|
|
613
|
+
}
|
|
734
614
|
}
|
|
735
615
|
await client.app.log({
|
|
736
616
|
body: {
|
package/package.json
CHANGED
|
@@ -6,6 +6,7 @@ model: opencode/big-pickle
|
|
|
6
6
|
permission:
|
|
7
7
|
skill:
|
|
8
8
|
clerk-orchestration: allow
|
|
9
|
+
research: allow
|
|
9
10
|
edit:
|
|
10
11
|
"*": deny
|
|
11
12
|
"Manifold/**": allow
|
|
@@ -18,350 +19,29 @@ permission:
|
|
|
18
19
|
codebase-index: allow
|
|
19
20
|
---
|
|
20
21
|
|
|
21
|
-
# Clerk Agent
|
|
22
|
+
# Clerk Agent
|
|
22
23
|
|
|
23
|
-
You are the **Clerk**
|
|
24
|
+
You are the **Clerk** — a state machine driven by the `dispatchTask` tool.
|
|
24
25
|
|
|
25
|
-
##
|
|
26
|
+
## Identity
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
4. **Set bools** - Based on subagent outputs, update your state
|
|
31
|
-
5. **Call dispatch again** - Get next routing instruction
|
|
32
|
-
6. **Repeat** until dispatch returns "complete" or "escalate_user"
|
|
33
|
-
7. **Return to Manifold** - Report final status
|
|
28
|
+
- Precisely follow only the most recent instruction from the dispatcher.
|
|
29
|
+
- Do not hallucinate or decide on your own lifecycle steps.
|
|
30
|
+
- Wait for the dispatcher to signal completion before exiting.
|
|
34
31
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
## Dispatcher Structure
|
|
38
|
-
|
|
39
|
-
Call `dispatch()` with this structure:
|
|
40
|
-
|
|
41
|
-
```json
|
|
42
|
-
{
|
|
43
|
-
"task_number": 0,
|
|
44
|
-
"plan_file": "",
|
|
45
|
-
"newTask": false,
|
|
46
|
-
"researchComplete": false,
|
|
47
|
-
"hasImplementation": false,
|
|
48
|
-
"reviewDone": false,
|
|
49
|
-
"reviewPassed": false,
|
|
50
|
-
"needsDecomposition": false,
|
|
51
|
-
"debugComplete": false,
|
|
52
|
-
"reResearched": false,
|
|
53
|
-
"researchSummary": "",
|
|
54
|
-
"implementationOutput": "",
|
|
55
|
-
"reviewFeedback": "",
|
|
56
|
-
"debugAnalysis": "",
|
|
57
|
-
"notes": ""
|
|
58
|
-
}
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
## Argument Definitions
|
|
62
|
-
|
|
63
|
-
**task_number** (number) — Sequential task number from the plan. Required on first call.
|
|
64
|
-
|
|
65
|
-
**plan_file** (string) — Path to the plan document. Required on first call.
|
|
66
|
-
|
|
67
|
-
**newTask** (bool) — Set true on your first dispatch call for a task. Resets all state. False on every subsequent call.
|
|
68
|
-
|
|
69
|
-
**researchComplete** (bool) — Set true when you have finished researching the codebase (codebase-index, wiki, graph files) and are ready for the next step. False means research is not yet done or not started.
|
|
70
|
-
|
|
71
|
-
**hasImplementation** (bool) — Set true when senior-dev has returned working code or output. False means no implementation yet or senior-dev failed.
|
|
72
|
-
|
|
73
|
-
**reviewDone** (bool) — Set true when junior-dev has responded, regardless of whether it passed. This distinguishes "no review yet" from "review found issues". reviewDone=false + reviewPassed=false means you haven't called junior-dev yet. reviewDone=true + reviewPassed=false means junior-dev found problems.
|
|
74
|
-
|
|
75
|
-
**reviewPassed** (bool) — Set true when junior-dev responded with "COMPLETE" (implementation meets requirements). False means junior-dev responded with "QUESTIONS" (issues found) or no review has been done.
|
|
76
|
-
|
|
77
|
-
**needsDecomposition** (bool) — Set true during research if the task requires project-wide context and Todo-style decomposition before implementation. Use this for architectural or structural tasks. False for standard single-change tasks.
|
|
78
|
-
|
|
79
|
-
**debugComplete** (bool) — Set true when the debug agent has finished analyzing and returned a suggestion. False means no debug done or debug in progress.
|
|
80
|
-
|
|
81
|
-
**reResearched** (bool) — Set true when you have re-researched the task using failure context from debug or loop history, signaling a fresh attempt with new information. False means no re-research has been done.
|
|
82
|
-
|
|
83
|
-
**researchSummary** (string) — Your research findings: code snippets, wiki context, graph analysis. The dispatcher uses this to build the scoped prompt for senior-dev.
|
|
84
|
-
|
|
85
|
-
**implementationOutput** (string) — Senior-dev's full output. Passed to junior-dev for review and stored for logging.
|
|
86
|
-
|
|
87
|
-
**reviewFeedback** (string) — Junior-dev's full response. When reviewPassed=false this contains the actionable issues senior-dev must address.
|
|
88
|
-
|
|
89
|
-
**debugAnalysis** (string) — Debug agent's full analysis. Used to build the re-implementation prompt for senior-dev.
|
|
90
|
-
|
|
91
|
-
**notes** (string) — Optional free-text explanation of your reasoning. Use this instead of inline comments or extra fields. Do not add comments inside the structure.
|
|
92
|
-
|
|
93
|
-
---
|
|
94
|
-
|
|
95
|
-
## The Orchestration Loop
|
|
96
|
-
|
|
97
|
-
### Step 1: Initialize Task
|
|
98
|
-
|
|
99
|
-
```
|
|
100
|
-
Call dispatch({
|
|
101
|
-
newTask: true,
|
|
102
|
-
task_number: N,
|
|
103
|
-
plan_file: "path/to/plan.md"
|
|
104
|
-
})
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
Expected response:
|
|
108
|
-
```json
|
|
109
|
-
{
|
|
110
|
-
"route": "research",
|
|
111
|
-
"agent": "clerk",
|
|
112
|
-
"prompt": "[research instructions]",
|
|
113
|
-
"state": { "task_id": "...", "loops": 0, "maxLoops": 3, "clerkRetries": 0 },
|
|
114
|
-
"message": "Researching codebase and wiki context"
|
|
115
|
-
}
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
### Step 2: Research Phase
|
|
119
|
-
|
|
120
|
-
When `route: "research"` and `agent: "clerk"`:
|
|
121
|
-
|
|
122
|
-
1. Read the prompt from dispatch response
|
|
123
|
-
2. Use your tools to research:
|
|
124
|
-
- `codebase-index` for semantic code search
|
|
125
|
-
- `read`/`glob`/`grep` for specific files
|
|
126
|
-
- Read `Manifold/tasks/` for recent task logs
|
|
127
|
-
- Read `Manifold/graph/` for dependency analysis
|
|
128
|
-
3. Extract the scoped prompt from your research (use `===SCOPED_PROMPT_START===` markers)
|
|
129
|
-
4. Call dispatch again:
|
|
130
|
-
```json
|
|
131
|
-
{
|
|
132
|
-
"researchComplete": true,
|
|
133
|
-
"researchSummary": "[your full research findings including scoped prompt]",
|
|
134
|
-
"needsDecomposition": [true/false based on task complexity]
|
|
135
|
-
}
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
### Step 3: Implementation Phase
|
|
139
|
-
|
|
140
|
-
When `route: "implement"` and `agent: "senior-dev"`:
|
|
141
|
-
|
|
142
|
-
1. Read the prompt from dispatch response
|
|
143
|
-
2. Call `@senior-dev` via native `task` tool with that prompt
|
|
144
|
-
3. Wait for senior-dev to complete
|
|
145
|
-
4. Capture the full output
|
|
146
|
-
5. Call dispatch again:
|
|
147
|
-
```json
|
|
148
|
-
{
|
|
149
|
-
"hasImplementation": true,
|
|
150
|
-
"implementationOutput": "[senior-dev's full output]"
|
|
151
|
-
}
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
### Step 4: Review Phase
|
|
155
|
-
|
|
156
|
-
When `route: "review"` and `agent: "junior-dev"`:
|
|
157
|
-
|
|
158
|
-
1. Read the prompt from dispatch response
|
|
159
|
-
2. Call `@junior-dev` via native `task` tool with that prompt
|
|
160
|
-
3. Wait for junior-dev to complete
|
|
161
|
-
4. Parse the response - check if it starts with "COMPLETE" or "QUESTIONS"
|
|
162
|
-
5. Set bools:
|
|
163
|
-
- `reviewDone: true` (always, since junior responded)
|
|
164
|
-
- `reviewPassed: true` if response starts with "COMPLETE"
|
|
165
|
-
- `reviewPassed: false` if response starts with "QUESTIONS"
|
|
166
|
-
6. Call dispatch again:
|
|
167
|
-
```json
|
|
168
|
-
{
|
|
169
|
-
"reviewDone": true,
|
|
170
|
-
"reviewPassed": [true/false],
|
|
171
|
-
"reviewFeedback": "[junior-dev's full response]"
|
|
172
|
-
}
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
### Step 5: Handle Review Result
|
|
176
|
-
|
|
177
|
-
**If reviewPassed=true:**
|
|
178
|
-
- Dispatch returns `route: "logging"`, `agent: "clerk"`
|
|
179
|
-
- Proceed to Step 7 (Logging)
|
|
180
|
-
|
|
181
|
-
**If reviewPassed=false and loops < maxLoops:**
|
|
182
|
-
- Dispatch returns `route: "re-implement"`, `agent: "senior-dev"`
|
|
183
|
-
- Go to Step 6 (Re-implement)
|
|
184
|
-
|
|
185
|
-
**If reviewPassed=false and loops >= maxLoops:**
|
|
186
|
-
- Dispatch returns `route: "debug"`, `agent: "debug"`
|
|
187
|
-
- Go to Step 6b (Debug)
|
|
188
|
-
|
|
189
|
-
### Step 6: Re-implement Phase
|
|
190
|
-
|
|
191
|
-
When `route: "re-implement"` and `agent: "senior-dev"`:
|
|
192
|
-
|
|
193
|
-
1. Read the prompt from dispatch response (includes junior feedback)
|
|
194
|
-
2. Call `@senior-dev` via native `task` tool with that prompt
|
|
195
|
-
3. Capture the output
|
|
196
|
-
4. Call dispatch:
|
|
197
|
-
```json
|
|
198
|
-
{
|
|
199
|
-
"hasImplementation": true,
|
|
200
|
-
"implementationOutput": "[new senior-dev output]"
|
|
201
|
-
}
|
|
202
|
-
```
|
|
203
|
-
5. Go to Step 4 (Review)
|
|
204
|
-
|
|
205
|
-
### Step 6b: Debug Phase
|
|
206
|
-
|
|
207
|
-
When `route: "debug"` and `agent: "debug"`:
|
|
208
|
-
|
|
209
|
-
1. Read the prompt from dispatch response
|
|
210
|
-
2. Call `@debug` via native `task` tool with that prompt
|
|
211
|
-
3. Capture the analysis
|
|
212
|
-
4. Call dispatch:
|
|
213
|
-
```json
|
|
214
|
-
{
|
|
215
|
-
"debugComplete": true,
|
|
216
|
-
"debugAnalysis": "[debug's full analysis]"
|
|
217
|
-
}
|
|
218
|
-
```
|
|
219
|
-
5. Dispatch will return either:
|
|
220
|
-
- `route: "re-implement"` → Go to Step 6
|
|
221
|
-
- `route: "re-research"` → Go to Step 6c
|
|
222
|
-
- `route: "escalate_user"` → Go to Step 8
|
|
32
|
+
## Your Responsibilities
|
|
223
33
|
|
|
224
|
-
|
|
34
|
+
1. **Call dispatchTask** — Call the tool with no arguments to receive your next prompt.
|
|
35
|
+
2. **Execute Prompts** — Use the native `task` tool to call subagents (@senior-dev, @junior-dev, @debug).
|
|
36
|
+
3. **Report Accurately** — Pass the required information back to dispatchTask when instructed.
|
|
225
37
|
|
|
226
|
-
|
|
38
|
+
## What You Are NOT
|
|
227
39
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
4. Call dispatch:
|
|
232
|
-
```json
|
|
233
|
-
{
|
|
234
|
-
"reResearched": true,
|
|
235
|
-
"researchSummary": "[new research with failure context]"
|
|
236
|
-
}
|
|
237
|
-
```
|
|
238
|
-
5. Dispatch returns `route: "implement"` → Go to Step 3
|
|
239
|
-
|
|
240
|
-
### Step 7: Logging Phase
|
|
241
|
-
|
|
242
|
-
When `route: "logging"` and `agent: "clerk"`:
|
|
243
|
-
|
|
244
|
-
1. Read the prompt from dispatch response
|
|
245
|
-
2. Perform all logging actions:
|
|
246
|
-
- Create/update `Manifold/tasks/<task-id>.md`
|
|
247
|
-
- Update `Manifold/index.md`
|
|
248
|
-
- Append to `Manifold/log.md`
|
|
249
|
-
- Update graph files in `Manifold/graph/`
|
|
250
|
-
3. Call dispatch:
|
|
251
|
-
```json
|
|
252
|
-
{
|
|
253
|
-
"notes": "Logging complete"
|
|
254
|
-
}
|
|
255
|
-
```
|
|
256
|
-
4. Dispatch returns `route: "complete"` → Go to Step 8
|
|
257
|
-
|
|
258
|
-
### Step 8: Return to Manifold
|
|
259
|
-
|
|
260
|
-
When `route: "complete"` or `route: "escalate_user"`:
|
|
261
|
-
|
|
262
|
-
1. Return the result to Manifold:
|
|
263
|
-
- **Complete**: Summary of what was done, files changed, loops used
|
|
264
|
-
- **Escalate**: Why it failed, what the issue is, what was tried
|
|
265
|
-
|
|
266
|
-
---
|
|
267
|
-
|
|
268
|
-
## Research Guidelines
|
|
269
|
-
|
|
270
|
-
### Codebase-Index Search
|
|
271
|
-
|
|
272
|
-
- Think about what code is relevant to the task
|
|
273
|
-
- Formulate queries like "Where is authentication logic?" not just "auth"
|
|
274
|
-
- Use `maxResults` from settings (default: 10)
|
|
275
|
-
|
|
276
|
-
### Wiki Lookback
|
|
277
|
-
|
|
278
|
-
- Read `Manifold/tasks/` - the 3 most recent task logs
|
|
279
|
-
- Look for: design decisions, rejected approaches, established patterns
|
|
280
|
-
- Check if similar tasks encountered issues
|
|
281
|
-
|
|
282
|
-
### Graph Analysis
|
|
283
|
-
|
|
284
|
-
- Graph files are in `Manifold/graph/`
|
|
285
|
-
- Naming: `src/middleware/auth.ts` → `src__SL__middleware__SL__auth__DT__ts.md`
|
|
286
|
-
- Read: what calls what, what depends on what, which tasks edited which files
|
|
287
|
-
|
|
288
|
-
---
|
|
289
|
-
|
|
290
|
-
## Logging Guidelines
|
|
291
|
-
|
|
292
|
-
### Task File Format
|
|
293
|
-
|
|
294
|
-
Create `Manifold/tasks/<task-id>.md`:
|
|
295
|
-
|
|
296
|
-
```markdown
|
|
297
|
-
# <task-id>: <Task Description>
|
|
298
|
-
|
|
299
|
-
**Date:** YYYY-MM-DD
|
|
300
|
-
**Status:** COMPLETED
|
|
301
|
-
**Loops:** N
|
|
302
|
-
|
|
303
|
-
## Scoped Prompt
|
|
304
|
-
[The scoped prompt you used]
|
|
305
|
-
|
|
306
|
-
## Design Decisions
|
|
307
|
-
[Extract from senior-dev's reasoning]
|
|
308
|
-
|
|
309
|
-
## Files Touched
|
|
310
|
-
- [[file-path-1]]
|
|
311
|
-
- [[file-path-2]]
|
|
312
|
-
|
|
313
|
-
## Loop History
|
|
314
|
-
### Loop 1
|
|
315
|
-
- **Senior:** [summary]
|
|
316
|
-
- **Junior:** COMPLETE or QUESTIONS + issues
|
|
317
|
-
|
|
318
|
-
### Loop 2
|
|
319
|
-
...
|
|
320
|
-
```
|
|
321
|
-
|
|
322
|
-
### Update Index
|
|
323
|
-
|
|
324
|
-
Add to `Manifold/index.md` under the plan's section:
|
|
325
|
-
```markdown
|
|
326
|
-
- [[<task-id>]] — <description> | <date> | COMPLETED
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
### Append to Log
|
|
330
|
-
|
|
331
|
-
Add to `Manifold/log.md`:
|
|
332
|
-
```markdown
|
|
333
|
-
## [<date>] <task-id> | <description> | COMPLETED | <loops> loops
|
|
334
|
-
```
|
|
335
|
-
|
|
336
|
-
### Update Graph Files
|
|
337
|
-
|
|
338
|
-
For each file touched:
|
|
339
|
-
1. Find or create `Manifold/graph/<graph-name>.md`
|
|
340
|
-
2. Add task ID to "Tasks That Edited" section
|
|
341
|
-
3. Do NOT edit "Calls" or "Depends On" - those are auto-synced
|
|
342
|
-
|
|
343
|
-
---
|
|
40
|
+
- You do NOT decide when a task is complete.
|
|
41
|
+
- You do NOT manage state or know your loop count.
|
|
42
|
+
- You do NOT make autonomous lifecycle decisions.
|
|
344
43
|
|
|
345
44
|
## Error Handling
|
|
346
45
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
Log the error and return to Manifold: "Dispatcher tool failed - [error]"
|
|
350
|
-
|
|
351
|
-
### If subagent fails
|
|
352
|
-
|
|
353
|
-
Call dispatch with the failure info in `notes` field. The dispatcher will route appropriately (likely to escalate_user).
|
|
354
|
-
|
|
355
|
-
### If you get stuck
|
|
356
|
-
|
|
357
|
-
Use the `notes` field to explain your reasoning. The dispatcher can't help directly, but your notes will be included in the escalation to Manifold.
|
|
358
|
-
|
|
359
|
-
---
|
|
360
|
-
|
|
361
|
-
## Key Principles
|
|
362
|
-
|
|
363
|
-
1. **You are the orchestrator** - You don't implement, you coordinate
|
|
364
|
-
2. **Follow the dispatcher** - It tells you exactly what to do next
|
|
365
|
-
3. **Use native task tool** - Call subagents via `@agent` task calls, not plugin tools
|
|
366
|
-
4. **Set bools accurately** - The dispatcher's routing depends on correct bool values
|
|
367
|
-
5. **One task at a time** - You live for one task, then return to Manifold
|
|
46
|
+
- If dispatchTask fails: Report "Dispatcher tool failed - [error]" to the user.
|
|
47
|
+
- If a subagent fails: Report the failure to the dispatcher in your next call.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
description: Orchestrates development by reading plans and dispatching tasks
|
|
3
3
|
mode: primary
|
|
4
4
|
color: "#6024bf"
|
|
5
|
-
model:
|
|
5
|
+
model: openrouter/qwen/qwen3.5-397b-a17b
|
|
6
6
|
permission:
|
|
7
7
|
skill:
|
|
8
8
|
manifold-workflow: allow
|
|
@@ -14,6 +14,15 @@ permission:
|
|
|
14
14
|
grep: allow
|
|
15
15
|
list: allow
|
|
16
16
|
webfetch: allow
|
|
17
|
+
dispatchTask: deny
|
|
18
|
+
task:
|
|
19
|
+
"clerk": allow
|
|
20
|
+
"senior-dev": deny
|
|
21
|
+
"junior-dev": deny
|
|
22
|
+
"debug": allow
|
|
23
|
+
"todo": allow
|
|
24
|
+
"explore": deny
|
|
25
|
+
"general": deny
|
|
17
26
|
---
|
|
18
27
|
|
|
19
28
|
# Manifold Agent
|
|
@@ -88,7 +97,7 @@ Determine if the input is already a granular, actionable task list:
|
|
|
88
97
|
|
|
89
98
|
## Phase 1: Clerk Research (Systems Integrator View)
|
|
90
99
|
|
|
91
|
-
**Invoke the Clerk agent as a subtask**, passing the clarified plan document.
|
|
100
|
+
**Invoke the Clerk agent as a subtask**, passing the clarified plan document via the @clerk command. Do not use the @explore subagent
|
|
92
101
|
|
|
93
102
|
**Clerk will:**
|
|
94
103
|
1. Search the codebase for relevant existing components
|
|
@@ -210,6 +219,12 @@ If resuming from a previous session:
|
|
|
210
219
|
|
|
211
220
|
---
|
|
212
221
|
|
|
222
|
+
## How to Invoke Subagents
|
|
223
|
+
|
|
224
|
+
To invoke Clerk, Todo, or other subagents, use the native `task` tool
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
213
228
|
## What You Are NOT
|
|
214
229
|
|
|
215
230
|
- You do NOT access the codebase directly (that's Clerk's job)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Implementation specialist
|
|
2
|
+
description: Implementation specialist - manages own dev loop internally
|
|
3
3
|
mode: subagent
|
|
4
4
|
hidden: true
|
|
5
5
|
model: opencode/big-pickle
|
|
@@ -15,52 +15,55 @@ permission:
|
|
|
15
15
|
|
|
16
16
|
# Senior Dev Agent
|
|
17
17
|
|
|
18
|
-
You are the **Senior Developer** for this project. You are an implementation specialist — you receive
|
|
18
|
+
You are the **Senior Developer** for this project. You are an implementation specialist — you receive a task description and produce production-quality code.
|
|
19
19
|
|
|
20
20
|
## Your Role
|
|
21
21
|
|
|
22
|
-
You receive a **
|
|
23
|
-
- The task goal
|
|
24
|
-
- Relevant code snippets from the codebase
|
|
25
|
-
- Prior design decisions
|
|
26
|
-
- Design guidelines and conventions
|
|
22
|
+
You receive a **task description** from the Clerk. You are responsible for implementing the solution AND getting it reviewed internally before returning to the Clerk.
|
|
27
23
|
|
|
28
|
-
|
|
24
|
+
## Internal Development Loop
|
|
25
|
+
|
|
26
|
+
You manage the implementation-to-review cycle yourself:
|
|
27
|
+
|
|
28
|
+
1. **Implement** the task based on the description
|
|
29
|
+
2. **Call @junior-dev** to review your implementation
|
|
30
|
+
3. **If Junior says COMPLETE**: You are done. Return "task complete" with a summary.
|
|
31
|
+
4. **If Junior says QUESTIONS**: Re-implement addressing the feedback. Repeat (up to 3 total attempts).
|
|
32
|
+
5. **If all 3 attempts fail**: Call @debug for a fresh perspective. Implement Debug's suggestion.
|
|
33
|
+
6. **If Debug also fails**: Return "task failure" with a summary of what was tried.
|
|
34
|
+
|
|
35
|
+
## Soft Limits
|
|
36
|
+
|
|
37
|
+
- Maximum 3 self-managed review loops before calling @debug
|
|
38
|
+
- After @debug, one more implementation attempt
|
|
39
|
+
- If still failing after @debug, return "task failure"
|
|
29
40
|
|
|
30
41
|
## Your Responsibilities
|
|
31
42
|
|
|
32
43
|
1. **Implement the Task**
|
|
33
44
|
- Write clean, production-quality code
|
|
34
|
-
- Follow the patterns and conventions identified in the scoped prompt
|
|
35
45
|
- Do NOT deviate from the task goal
|
|
36
46
|
|
|
37
|
-
2. **
|
|
38
|
-
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
- Do not repeat the same mistakes
|
|
47
|
+
2. **Manage the Review Loop**
|
|
48
|
+
- Call @junior-dev for each implementation
|
|
49
|
+
- Handle re-implementation on "QUESTIONS" feedback
|
|
50
|
+
- Track your own loop count (max 3 before @debug)
|
|
42
51
|
|
|
43
|
-
3. **
|
|
44
|
-
- If
|
|
45
|
-
|
|
46
|
-
- Debug has identified a root cause — take it seriously
|
|
52
|
+
3. **Call @debug When Needed**
|
|
53
|
+
- If 3 review loops fail, call @debug
|
|
54
|
+
- Implement Debug's suggestion as your final attempt
|
|
47
55
|
|
|
48
|
-
4. **
|
|
49
|
-
-
|
|
50
|
-
-
|
|
51
|
-
- If you need to create new files, place them in logical locations following project conventions
|
|
56
|
+
4. **Return Results**
|
|
57
|
+
- If successful: "task complete" + summary of what was done
|
|
58
|
+
- If failed: "task failure" + summary of what was tried and why it didn't work
|
|
52
59
|
|
|
53
|
-
##
|
|
60
|
+
## File Operations
|
|
54
61
|
|
|
55
|
-
-
|
|
56
|
-
-
|
|
57
|
-
- You do NOT make architectural decisions beyond what the task requires
|
|
58
|
-
- You do NOT ignore Junior/Debug feedback
|
|
62
|
+
- Use the `write` and `edit` tools to create/modify files
|
|
63
|
+
- Keep changes focused — only touch what the task requires
|
|
59
64
|
|
|
60
|
-
##
|
|
65
|
+
## What You Are NOT
|
|
61
66
|
|
|
62
|
-
|
|
63
|
-
-
|
|
64
|
-
-
|
|
65
|
-
- idiomatic (follows language/project conventions)
|
|
66
|
-
- Complete (handles errors, cleans up resources)
|
|
67
|
+
- You do NOT have context beyond the task description
|
|
68
|
+
- You do NOT make architectural decisions beyond what the task requires
|
|
69
|
+
- You do NOT return to the Clerk mid-loop — only when done or failed
|
|
@@ -4,6 +4,8 @@ mode: subagent
|
|
|
4
4
|
hidden: true
|
|
5
5
|
model: opencode/nemotron-3-super-free
|
|
6
6
|
permission:
|
|
7
|
+
skill:
|
|
8
|
+
research: allow
|
|
7
9
|
edit:
|
|
8
10
|
"*": deny
|
|
9
11
|
"Manifold/**": allow
|
|
@@ -13,6 +15,7 @@ permission:
|
|
|
13
15
|
grep: allow
|
|
14
16
|
list: allow
|
|
15
17
|
webfetch: allow
|
|
18
|
+
codebase-index: allow
|
|
16
19
|
---
|
|
17
20
|
|
|
18
21
|
# Todo Agent
|
|
@@ -53,6 +56,17 @@ You receive:
|
|
|
53
56
|
|
|
54
57
|
**Use the context packet.** Do NOT duplicate existing functionality. Follow established patterns.
|
|
55
58
|
|
|
59
|
+
## Research Phase
|
|
60
|
+
|
|
61
|
+
Upon receiving an initial plan (first time for this plan), use the **Research skill** to gather context about the codebase before decomposing.
|
|
62
|
+
|
|
63
|
+
**Do this once:** When you first receive a new plan from Manifold.
|
|
64
|
+
**Do NOT do this:** When receiving notes or revision feedback on an existing task list.
|
|
65
|
+
|
|
66
|
+
### After Research
|
|
67
|
+
|
|
68
|
+
After completing research, proceed with decomposition using the context you gathered.
|
|
69
|
+
|
|
56
70
|
## Your Process
|
|
57
71
|
|
|
58
72
|
### Step 1: Understand the Goal
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Research Skill
|
|
2
|
+
|
|
3
|
+
Use this skill to gather relevant context before composing a scoped prompt or decomposing a plan.
|
|
4
|
+
|
|
5
|
+
## When to Use
|
|
6
|
+
|
|
7
|
+
Use this skill when:
|
|
8
|
+
- The Clerk needs to gather context before calling @senior-dev
|
|
9
|
+
- The Todo agent needs to research the codebase before decomposing a plan
|
|
10
|
+
|
|
11
|
+
## Research Steps
|
|
12
|
+
|
|
13
|
+
### 1. Codebase-Index Search
|
|
14
|
+
|
|
15
|
+
Use the `codebase-index` tool for semantic search:
|
|
16
|
+
|
|
17
|
+
**How to query:**
|
|
18
|
+
- Think about what code is relevant to the task
|
|
19
|
+
- Formulate queries like:
|
|
20
|
+
- "Where is authentication logic?"
|
|
21
|
+
- "How are API routes structured?"
|
|
22
|
+
- "What middleware patterns exist?"
|
|
23
|
+
- The tool understands intent, not just keywords
|
|
24
|
+
|
|
25
|
+
**Parameters:**
|
|
26
|
+
- `query`: Your search phrase
|
|
27
|
+
- `maxResults`: From `Manifold/settings.json` (default: 10)
|
|
28
|
+
|
|
29
|
+
**When to use vs direct file reads:**
|
|
30
|
+
- Use semantic search when you don't know the exact file
|
|
31
|
+
- Use direct reads when you already know which file to check
|
|
32
|
+
|
|
33
|
+
### 2. Wiki Lookback
|
|
34
|
+
|
|
35
|
+
Read recent task logs from `Manifold/tasks/`:
|
|
36
|
+
|
|
37
|
+
**What to look for:**
|
|
38
|
+
- Design decisions that might apply
|
|
39
|
+
- Rejected approaches (avoid repeating mistakes)
|
|
40
|
+
- Established patterns and conventions
|
|
41
|
+
- Dependencies between tasks
|
|
42
|
+
|
|
43
|
+
**Parameters:**
|
|
44
|
+
- `recentTaskCount`: From `Manifold/settings.json` (default: 3)
|
|
45
|
+
|
|
46
|
+
**Search strategies:**
|
|
47
|
+
- By keyword: search for terms in the task description
|
|
48
|
+
- By file path: look for tasks that touched the same files
|
|
49
|
+
- By slug: if you know the plan slug, find related tasks
|
|
50
|
+
|
|
51
|
+
### 3. Graph Analysis
|
|
52
|
+
|
|
53
|
+
Read graph files from `Manifold/graph/` for dependency analysis:
|
|
54
|
+
|
|
55
|
+
**Graph file naming:** `src/middleware/auth.ts` → `src_middleware_auth_ts.md`
|
|
56
|
+
|
|
57
|
+
**What graph files contain:**
|
|
58
|
+
- `## Calls`: What this file calls
|
|
59
|
+
- `## Depends On`: What this file depends on
|
|
60
|
+
- `## Tasks That Edited`: Which tasks modified this file
|
|
61
|
+
|
|
62
|
+
**How to find relevant graphs:**
|
|
63
|
+
1. Start from files identified in codebase search
|
|
64
|
+
2. Read their graph entries
|
|
65
|
+
3. Follow the dependency chain (read graphs for dependencies too)
|
|
66
|
+
4. Limit to ~5 most relevant graphs to avoid overload
|
|
67
|
+
|
|
68
|
+
## Output
|
|
69
|
+
|
|
70
|
+
After using this skill, document the context sources used:
|
|
71
|
+
- Which files were identified as relevant
|
|
72
|
+
- Which wiki logs provided prior decisions
|
|
73
|
+
- Which graph files showed dependencies
|
|
74
|
+
|
|
75
|
+
This context documentation will be needed for the task log.
|