@s_s/harmonia 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/README.md +3 -0
  2. package/build/core/dispatch.d.ts +38 -0
  3. package/build/core/dispatch.js +156 -0
  4. package/build/core/dispatch.js.map +1 -0
  5. package/build/core/docs.d.ts +19 -0
  6. package/build/core/docs.js +59 -0
  7. package/build/core/docs.js.map +1 -0
  8. package/build/core/overrides.d.ts +62 -0
  9. package/build/core/overrides.js +206 -0
  10. package/build/core/overrides.js.map +1 -0
  11. package/build/core/registry.d.ts +72 -0
  12. package/build/core/registry.js +121 -0
  13. package/build/core/registry.js.map +1 -0
  14. package/build/core/reviews.d.ts +26 -0
  15. package/build/core/reviews.js +83 -0
  16. package/build/core/reviews.js.map +1 -0
  17. package/build/core/state.d.ts +26 -0
  18. package/build/core/state.js +103 -0
  19. package/build/core/state.js.map +1 -0
  20. package/build/core/types.d.ts +181 -0
  21. package/build/core/types.js +6 -0
  22. package/build/core/types.js.map +1 -0
  23. package/build/core/workflow.d.ts +13 -0
  24. package/build/core/workflow.js +63 -0
  25. package/build/core/workflow.js.map +1 -0
  26. package/build/index.d.ts +15 -0
  27. package/build/index.js +57 -0
  28. package/build/index.js.map +1 -0
  29. package/build/setup/inject.d.ts +34 -0
  30. package/build/setup/inject.js +115 -0
  31. package/build/setup/inject.js.map +1 -0
  32. package/build/setup/templates.d.ts +21 -0
  33. package/build/setup/templates.js +177 -0
  34. package/build/setup/templates.js.map +1 -0
  35. package/build/tools/approve-doc.d.ts +6 -0
  36. package/build/tools/approve-doc.js +79 -0
  37. package/build/tools/approve-doc.js.map +1 -0
  38. package/build/tools/dispatch-role.d.ts +16 -0
  39. package/build/tools/dispatch-role.js +232 -0
  40. package/build/tools/dispatch-role.js.map +1 -0
  41. package/build/tools/doc-tools.d.ts +8 -0
  42. package/build/tools/doc-tools.js +102 -0
  43. package/build/tools/doc-tools.js.map +1 -0
  44. package/build/tools/get-project-status.d.ts +8 -0
  45. package/build/tools/get-project-status.js +230 -0
  46. package/build/tools/get-project-status.js.map +1 -0
  47. package/build/tools/get-role-prompt.d.ts +7 -0
  48. package/build/tools/get-role-prompt.js +95 -0
  49. package/build/tools/get-role-prompt.js.map +1 -0
  50. package/build/tools/override-tools.d.ts +6 -0
  51. package/build/tools/override-tools.js +129 -0
  52. package/build/tools/override-tools.js.map +1 -0
  53. package/build/tools/project-init.d.ts +6 -0
  54. package/build/tools/project-init.js +71 -0
  55. package/build/tools/project-init.js.map +1 -0
  56. package/build/tools/report-dispatch.d.ts +11 -0
  57. package/build/tools/report-dispatch.js +142 -0
  58. package/build/tools/report-dispatch.js.map +1 -0
  59. package/build/tools/setup-project.d.ts +8 -0
  60. package/build/tools/setup-project.js +88 -0
  61. package/build/tools/setup-project.js.map +1 -0
  62. package/build/tools/update-phase.d.ts +7 -0
  63. package/build/tools/update-phase.js +79 -0
  64. package/build/tools/update-phase.js.map +1 -0
  65. package/package.json +51 -0
  66. package/workflows/dev/roles/architect.md +66 -0
  67. package/workflows/dev/roles/developer.md +44 -0
  68. package/workflows/dev/roles/pm.md +99 -0
  69. package/workflows/dev/roles/tester.md +44 -0
  70. package/workflows/dev/workflow.json +134 -0
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Harmonia — Multi-agent orchestration MCP server with pluggable workflows.
4
+ *
5
+ * All project data is stored under the Harmonia data directory (platform-specific).
6
+ * Project source directories contain code only — no Harmonia artifacts.
7
+ *
8
+ * Provides tools for managing projects:
9
+ * - project_init: Register a project and create <data_dir>/<project_name>/ data dirs
10
+ * - get_project_status: View current project phase and progress
11
+ * - get_role_prompt: Get role prompts for agent setup
12
+ * - update_phase: Advance project phases
13
+ * - write_doc / read_doc / list_docs: Manage project documents
14
+ */
15
+ export {};
package/build/index.js ADDED
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Harmonia — Multi-agent orchestration MCP server with pluggable workflows.
4
+ *
5
+ * All project data is stored under the Harmonia data directory (platform-specific).
6
+ * Project source directories contain code only — no Harmonia artifacts.
7
+ *
8
+ * Provides tools for managing projects:
9
+ * - project_init: Register a project and create <data_dir>/<project_name>/ data dirs
10
+ * - get_project_status: View current project phase and progress
11
+ * - get_role_prompt: Get role prompts for agent setup
12
+ * - update_phase: Advance project phases
13
+ * - write_doc / read_doc / list_docs: Manage project documents
14
+ */
15
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
16
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
17
+ import { fileURLToPath } from 'node:url';
18
+ import { dirname, join, resolve } from 'node:path';
19
+ import { registerProjectInit } from './tools/project-init.js';
20
+ import { registerGetRolePrompt } from './tools/get-role-prompt.js';
21
+ import { registerUpdatePhase } from './tools/update-phase.js';
22
+ import { registerDocTools } from './tools/doc-tools.js';
23
+ import { registerGetProjectStatus } from './tools/get-project-status.js';
24
+ import { registerApproveDoc } from './tools/approve-doc.js';
25
+ import { registerOverrideTools } from './tools/override-tools.js';
26
+ import { registerDispatchRole } from './tools/dispatch-role.js';
27
+ import { registerReportDispatch } from './tools/report-dispatch.js';
28
+ import { registerSetupProject } from './tools/setup-project.js';
29
+ const __filename = fileURLToPath(import.meta.url);
30
+ const __dirname = dirname(__filename);
31
+ // Workflows directory is at the package root, sibling to build/
32
+ const WORKFLOWS_DIR = process.env.HARMONIA_WORKFLOWS_DIR ?? resolve(join(__dirname, '..', 'workflows'));
33
+ const server = new McpServer({
34
+ name: 'harmonia',
35
+ version: '0.1.0',
36
+ });
37
+ // Register all tools
38
+ registerProjectInit(server, WORKFLOWS_DIR);
39
+ registerGetRolePrompt(server, WORKFLOWS_DIR);
40
+ registerUpdatePhase(server, WORKFLOWS_DIR);
41
+ registerDocTools(server, WORKFLOWS_DIR);
42
+ registerGetProjectStatus(server, WORKFLOWS_DIR);
43
+ registerApproveDoc(server);
44
+ registerOverrideTools(server);
45
+ registerDispatchRole(server, WORKFLOWS_DIR);
46
+ registerReportDispatch(server);
47
+ registerSetupProject(server);
48
+ // Connect via stdio
49
+ async function main() {
50
+ const transport = new StdioServerTransport();
51
+ await server.connect(transport);
52
+ }
53
+ main().catch((err) => {
54
+ console.error('Fatal error:', err);
55
+ process.exit(1);
56
+ });
57
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAEhE,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,gEAAgE;AAChE,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC;AAExG,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IACzB,IAAI,EAAE,UAAU;IAChB,OAAO,EAAE,OAAO;CACnB,CAAC,CAAC;AAEH,qBAAqB;AACrB,mBAAmB,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AAC3C,qBAAqB,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AAC7C,mBAAmB,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AAC3C,gBAAgB,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AACxC,wBAAwB,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AAChD,kBAAkB,CAAC,MAAM,CAAC,CAAC;AAC3B,qBAAqB,CAAC,MAAM,CAAC,CAAC;AAC9B,oBAAoB,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AAC5C,sBAAsB,CAAC,MAAM,CAAC,CAAC;AAC/B,oBAAoB,CAAC,MAAM,CAAC,CAAC;AAE7B,oBAAoB;AACpB,KAAK,UAAU,IAAI;IACf,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AACpC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACjB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;IACnC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Setup injection — detect host agent type and inject PM guidance into config.
3
+ *
4
+ * V1 supports only OpenCode (AGENTS.md injection).
5
+ * The injection is idempotent — re-running replaces existing harmonia block.
6
+ */
7
+ import { type PromptTemplateParams } from './templates.js';
8
+ /** Supported host agent types */
9
+ export type HostAgentType = 'opencode' | 'claude-code' | 'codex';
10
+ /**
11
+ * Detect the host agent type for a given project directory.
12
+ *
13
+ * V1 heuristic:
14
+ * - Check for AGENTS.md → opencode
15
+ * - Check for .claude/ dir → claude-code
16
+ * - Default to opencode (most common)
17
+ *
18
+ * Future: accept explicit override via parameter.
19
+ */
20
+ export declare function detectHostAgent(projectDir: string): Promise<HostAgentType>;
21
+ /**
22
+ * Inject the Harmonia PM guidance block into a config file.
23
+ * If a harmonia block already exists, it is replaced (idempotent).
24
+ * If the file doesn't exist, it is created.
25
+ */
26
+ export declare function injectPrompt(projectDir: string, agentType: HostAgentType, params: PromptTemplateParams): Promise<{
27
+ filePath: string;
28
+ created: boolean;
29
+ replaced: boolean;
30
+ }>;
31
+ /**
32
+ * Remove the Harmonia block from a config file.
33
+ */
34
+ export declare function removePrompt(projectDir: string, agentType: HostAgentType): Promise<boolean>;
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Setup injection — detect host agent type and inject PM guidance into config.
3
+ *
4
+ * V1 supports only OpenCode (AGENTS.md injection).
5
+ * The injection is idempotent — re-running replaces existing harmonia block.
6
+ */
7
+ import { readFile, writeFile, mkdir } from 'node:fs/promises';
8
+ import { join, dirname } from 'node:path';
9
+ import { generateOpenCodePrompt, HARMONIA_MARKER_START, HARMONIA_MARKER_END, } from './templates.js';
10
+ /**
11
+ * Detect the host agent type for a given project directory.
12
+ *
13
+ * V1 heuristic:
14
+ * - Check for AGENTS.md → opencode
15
+ * - Check for .claude/ dir → claude-code
16
+ * - Default to opencode (most common)
17
+ *
18
+ * Future: accept explicit override via parameter.
19
+ */
20
+ export async function detectHostAgent(projectDir) {
21
+ // Check for .claude directory (Claude Code)
22
+ try {
23
+ await readFile(join(projectDir, '.claude', 'settings.json'), 'utf-8');
24
+ return 'claude-code';
25
+ }
26
+ catch {
27
+ // not claude-code
28
+ }
29
+ // Default to opencode
30
+ return 'opencode';
31
+ }
32
+ /**
33
+ * Get the config file path for a host agent type.
34
+ */
35
+ function getConfigPath(projectDir, agentType) {
36
+ switch (agentType) {
37
+ case 'opencode':
38
+ return join(projectDir, 'AGENTS.md');
39
+ case 'claude-code':
40
+ return join(projectDir, 'CLAUDE.md');
41
+ case 'codex':
42
+ return join(projectDir, 'AGENTS.md');
43
+ }
44
+ }
45
+ /**
46
+ * Inject the Harmonia PM guidance block into a config file.
47
+ * If a harmonia block already exists, it is replaced (idempotent).
48
+ * If the file doesn't exist, it is created.
49
+ */
50
+ export async function injectPrompt(projectDir, agentType, params) {
51
+ const filePath = getConfigPath(projectDir, agentType);
52
+ const prompt = generateOpenCodePrompt(params);
53
+ let existingContent = '';
54
+ let fileExists = true;
55
+ try {
56
+ existingContent = await readFile(filePath, 'utf-8');
57
+ }
58
+ catch {
59
+ fileExists = false;
60
+ }
61
+ let replaced = false;
62
+ let newContent;
63
+ if (fileExists && existingContent.includes(HARMONIA_MARKER_START)) {
64
+ // Replace existing harmonia block
65
+ const startIdx = existingContent.indexOf(HARMONIA_MARKER_START);
66
+ const endIdx = existingContent.indexOf(HARMONIA_MARKER_END) + HARMONIA_MARKER_END.length;
67
+ if (endIdx > startIdx) {
68
+ newContent = existingContent.substring(0, startIdx) + prompt + existingContent.substring(endIdx);
69
+ replaced = true;
70
+ }
71
+ else {
72
+ // Malformed markers — append
73
+ newContent = existingContent + '\n\n' + prompt + '\n';
74
+ }
75
+ }
76
+ else if (fileExists) {
77
+ // Append to existing file
78
+ newContent = existingContent + '\n\n' + prompt + '\n';
79
+ }
80
+ else {
81
+ // Create new file
82
+ newContent = prompt + '\n';
83
+ }
84
+ await mkdir(dirname(filePath), { recursive: true });
85
+ await writeFile(filePath, newContent, 'utf-8');
86
+ return { filePath, created: !fileExists, replaced };
87
+ }
88
+ /**
89
+ * Remove the Harmonia block from a config file.
90
+ */
91
+ export async function removePrompt(projectDir, agentType) {
92
+ const filePath = getConfigPath(projectDir, agentType);
93
+ try {
94
+ const content = await readFile(filePath, 'utf-8');
95
+ if (!content.includes(HARMONIA_MARKER_START))
96
+ return false;
97
+ const startIdx = content.indexOf(HARMONIA_MARKER_START);
98
+ const endIdx = content.indexOf(HARMONIA_MARKER_END) + HARMONIA_MARKER_END.length;
99
+ if (endIdx <= startIdx)
100
+ return false;
101
+ // Remove the block and any surrounding blank lines
102
+ let newContent = content.substring(0, startIdx) + content.substring(endIdx);
103
+ newContent = newContent.replace(/\n{3,}/g, '\n\n').trim();
104
+ if (newContent.length === 0) {
105
+ // File would be empty — could delete it, but safer to leave empty
106
+ newContent = '';
107
+ }
108
+ await writeFile(filePath, newContent + '\n', 'utf-8');
109
+ return true;
110
+ }
111
+ catch {
112
+ return false;
113
+ }
114
+ }
115
+ //# sourceMappingURL=inject.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inject.js","sourceRoot":"","sources":["../../src/setup/inject.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * PM guidance prompt template for OpenCode.
3
+ *
4
+ * This template is injected into the project's AGENTS.md to guide the host
5
+ * agent to act as the PM role in a Harmonia-managed project.
6
+ */
7
+ export interface PromptTemplateParams {
8
+ projectName: string;
9
+ projectDir: string;
10
+ workflow: string;
11
+ scale: string;
12
+ }
13
+ /**
14
+ * Generate the PM guidance prompt for OpenCode AGENTS.md injection.
15
+ */
16
+ export declare function generateOpenCodePrompt(params: PromptTemplateParams): string;
17
+ /**
18
+ * The marker tags used to identify Harmonia-injected content in AGENTS.md.
19
+ */
20
+ export declare const HARMONIA_MARKER_START = "<!-- harmonia:start -->";
21
+ export declare const HARMONIA_MARKER_END = "<!-- harmonia:end -->";
@@ -0,0 +1,177 @@
1
+ /**
2
+ * PM guidance prompt template for OpenCode.
3
+ *
4
+ * This template is injected into the project's AGENTS.md to guide the host
5
+ * agent to act as the PM role in a Harmonia-managed project.
6
+ */
7
+ /**
8
+ * Generate the PM guidance prompt for OpenCode AGENTS.md injection.
9
+ */
10
+ export function generateOpenCodePrompt(params) {
11
+ return `<!-- harmonia:start -->
12
+ ## Harmonia — Project Manager Mode
13
+
14
+ You are the **PM (Project Manager)** for project **${params.projectName}**.
15
+ Harmonia is managing the project workflow. You are the central coordinator — the only role that talks directly to the user.
16
+
17
+ - **Project directory**: ${params.projectDir}
18
+ - **Workflow**: ${params.workflow}
19
+ - **Scale**: ${params.scale}
20
+
21
+ ### Your Responsibilities
22
+
23
+ 1. **Communicate with the user** — clarify requirements, present documents for review, report progress
24
+ 2. **Drive the workflow** — advance phases, produce documents, dispatch tasks to team members
25
+ 3. **Coordinate the team** — dispatch roles, track sessions and dispatch progress, manage outputs
26
+ 4. **Ensure quality** — review documents, handle review cycles, verify deliverables
27
+
28
+ ### Available Harmonia Tools
29
+
30
+ | Tool | When to Use |
31
+ |------|-------------|
32
+ | \`get_project_status\` | Check current phase, progress, sessions, dispatches, pending reviews, next steps |
33
+ | \`get_role_prompt\` | View any role's prompt and configuration |
34
+ | \`update_phase\` | Advance or update a phase's status |
35
+ | \`write_doc\` | Write/update a project document (auto-triggers review if configured) |
36
+ | \`read_doc\` | Read a project document |
37
+ | \`list_docs\` | List all project documents |
38
+ | \`dispatch_role\` | Prepare data + create dispatch record for a team member (auto-detects reusable sessions) |
39
+ | \`report_dispatch\` | Report dispatch status: register agent session after launch, report completion/failure |
40
+ | \`approve_doc\` | Approve or reject a document after user review |
41
+ | \`list_pending_reviews\` | Check which documents are awaiting user approval |
42
+ | \`set_capability_override\` | Configure a role to use an external tool for a capability |
43
+ | \`set_review_override\` | Enable/disable review for a document type |
44
+ | \`get_overrides\` | View current override configuration |
45
+
46
+ ### Workflow Guide
47
+
48
+ #### Phase 1: Requirements Clarification (\`clarify\`)
49
+
50
+ 1. Talk to the user to understand their needs
51
+ 2. Write the PRD: \`write_doc(project_name, "prd", content)\`
52
+ 3. Write user stories: \`write_doc(project_name, "user-stories", content)\`
53
+ 4. If the project is medium/large, also write: FSD, prototype (HTML), project plan
54
+ 5. Handle review cycles — when \`write_doc\` returns "REVIEW REQUIRED", present the document to the user and wait for confirmation
55
+ 6. After all clarify-phase documents are approved, advance: \`update_phase(project_name, "clarify", "completed")\`
56
+
57
+ #### Phase 2: Design (\`design\`)
58
+
59
+ 1. Dispatch the architect: \`dispatch_role(project_name, "architect", task_brief)\`
60
+ 2. Follow the dispatch workflow (see below) to launch and track the architect
61
+ 3. The architect will produce: tech-design, task-breakdown (and optionally: data-model, api-design, risk-assessment)
62
+ 4. Review the architect's output, ask user for feedback if needed
63
+ 5. Advance: \`update_phase(project_name, "design", "completed")\`
64
+
65
+ #### Phase 3: Development (\`develop\`)
66
+
67
+ 1. Read the task breakdown: \`read_doc(project_name, "task-breakdown")\`
68
+ 2. Dispatch developers for each task (or batch): \`dispatch_role(project_name, "developer", task_brief)\`
69
+ 3. Developers can work in parallel if tasks are independent — each gets their own dispatch and session
70
+ 4. Track progress with \`get_project_status\` — it shows all active sessions and dispatch records
71
+ 5. Advance when all tasks are complete: \`update_phase(project_name, "develop", "completed")\`
72
+
73
+ #### Phase 4: Testing (\`test\`)
74
+
75
+ 1. Dispatch the tester: \`dispatch_role(project_name, "tester", task_brief)\`
76
+ 2. Follow the dispatch workflow to launch and track the tester
77
+ 3. Tester writes test plan, executes tests, produces test report
78
+ 4. If bugs are found, coordinate fixes with developers (re-dispatch as needed)
79
+ 5. Advance: \`update_phase(project_name, "test", "completed")\`
80
+
81
+ #### Phase 5: Delivery (\`deliver\`)
82
+
83
+ 1. Review all deliverables against user stories and acceptance criteria
84
+ 2. Present final results to the user
85
+ 3. Write retrospective: \`write_doc(project_name, "retrospective", content)\`
86
+ 4. Advance: \`update_phase(project_name, "deliver", "completed")\`
87
+
88
+ ### Dispatch Workflow (Critical — follow every time)
89
+
90
+ Dispatching a team member follows three steps:
91
+
92
+ #### Step 1: Dispatch
93
+ \`\`\`
94
+ dispatch_role(project_name, role, task_brief)
95
+ → Returns: data package + dispatch_id + session guidance
96
+ \`\`\`
97
+ Harmonia automatically:
98
+ - Creates a dispatch record for tracking
99
+ - Checks for reusable idle sessions and tells you whether to resume or launch new
100
+
101
+ #### Step 2: Launch & Report
102
+ Launch the agent based on the session guidance:
103
+ - **If reusable session found**: Resume the existing agent session (use the agent session ID provided)
104
+ - **If no reusable session**: Launch a new agent
105
+
106
+ After launching, immediately report:
107
+ \`\`\`
108
+ report_dispatch(project_name, dispatch_id, agent_session_id="<id from agent>", agent_type="opencode")
109
+ \`\`\`
110
+ This registers the session and marks the dispatch as running.
111
+
112
+ #### Step 3: Completion
113
+ When the agent finishes (process exits or session ends):
114
+ \`\`\`
115
+ report_dispatch(project_name, dispatch_id, status="completed")
116
+ \`\`\`
117
+ Or if it failed:
118
+ \`\`\`
119
+ report_dispatch(project_name, dispatch_id, status="failed", note="reason")
120
+ \`\`\`
121
+ Then check: \`get_project_status\` to verify outputs and determine next steps.
122
+
123
+ ### Launching Agents
124
+
125
+ #### If you are an OpenClaw agent (sessions_spawn)
126
+ Use \`sessions_spawn\` to launch a sub-agent. The sub-agent automatically shares the gateway-level MCP configuration, so it can use all Harmonia tools (write_doc, read_doc, etc.) without additional setup.
127
+
128
+ \`\`\`
129
+ sessions_spawn with:
130
+ - system prompt = the role prompt from dispatch_role
131
+ - task = the task brief
132
+ - The sub-agent has access to all configured MCP servers including Harmonia
133
+ \`\`\`
134
+
135
+ #### For other agents (shell exec)
136
+ Launch the agent via shell command (\`exec\`). You need to:
137
+ 1. Start the agent process with the role prompt as system instructions
138
+ 2. Pass the task brief and input documents as the initial message
139
+ 3. Wait for the process to exit
140
+
141
+ ### Session Recovery (after interruption)
142
+
143
+ If you were interrupted or are resuming from a previous session:
144
+
145
+ 1. **Start with** \`get_project_status\` — it shows everything: phases, active sessions, dispatch records, pending reviews
146
+ 2. **Check dispatch records** — any "running" dispatches may need verification (did the agent finish?)
147
+ 3. **Check sessions** — "active" sessions may have agents still running; "idle" sessions can be reused; "lost" sessions need re-dispatch
148
+ 4. **Follow the next steps** suggested by \`get_project_status\`
149
+
150
+ ### Document Review Flow
151
+
152
+ Some documents require user approval (PRD, prototype by default).
153
+ When \`write_doc\` returns "REVIEW REQUIRED":
154
+
155
+ 1. Present the full document to the user
156
+ 2. Ask if they approve or want changes
157
+ 3. If approved → call \`approve_doc(project_name, doc_id, true)\`
158
+ 4. If changes needed → revise and call \`write_doc\` again
159
+ 5. **Never skip review.** Unapproved documents must not be used as input for subsequent phases.
160
+
161
+ ### Important Rules
162
+
163
+ 1. **Always check status first** — start each session with \`get_project_status\` to understand where you are
164
+ 2. **Always report dispatch lifecycle** — dispatch → report launch → report completion. Never skip report_dispatch.
165
+ 3. **Document everything** — every phase output must be saved via \`write_doc\`
166
+ 4. **Don't skip phases** — follow the workflow order unless blocked
167
+ 5. **Don't make technical decisions** — that's the architect's job; ask them via \`dispatch_role\`
168
+ 6. **Don't write code** — that's the developer's job
169
+ 7. **Scale appropriately** — small projects don't need all documents; check the scale setting
170
+ <!-- harmonia:end -->`;
171
+ }
172
+ /**
173
+ * The marker tags used to identify Harmonia-injected content in AGENTS.md.
174
+ */
175
+ export const HARMONIA_MARKER_START = '<!-- harmonia:start -->';
176
+ export const HARMONIA_MARKER_END = '<!-- harmonia:end -->';
177
+ //# sourceMappingURL=templates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/setup/templates.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAA4B;IAC/D,OAAO;;;qDAG0C,MAAM,CAAC,WAAW;;;2BAG5C,MAAM,CAAC,UAAU;kBAC1B,MAAM,CAAC,QAAQ;eAClB,MAAM,CAAC,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBAuJL,CAAC;AACvB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,yBAAyB,CAAC;AAC/D,MAAM,CAAC,MAAM,mBAAmB,GAAG,uBAAuB,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * MCP Tool: approve_doc
3
+ * Approve or reject a document that is pending review.
4
+ */
5
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
6
+ export declare function registerApproveDoc(server: McpServer): void;
@@ -0,0 +1,79 @@
1
+ /**
2
+ * MCP Tool: approve_doc
3
+ * Approve or reject a document that is pending review.
4
+ */
5
+ import { z } from 'zod';
6
+ import { resolveReview, getPendingReviews } from '../core/reviews.js';
7
+ export function registerApproveDoc(server) {
8
+ server.tool('approve_doc', 'Approve or reject a document pending review. Call this after the user has reviewed the document and confirmed (or requested changes).', {
9
+ project_name: z.string().describe('Project name'),
10
+ doc_id: z.string().describe('Document ID to approve/reject'),
11
+ approved: z.boolean().describe('true = approved, false = rejected (needs revision)'),
12
+ comment: z.string().optional().describe('Optional comment — user feedback or reason for rejection'),
13
+ }, async ({ project_name, doc_id, approved, comment }) => {
14
+ try {
15
+ const status = approved ? 'approved' : 'rejected';
16
+ const review = await resolveReview(project_name, doc_id, status, comment);
17
+ if (approved) {
18
+ return {
19
+ content: [
20
+ {
21
+ type: 'text',
22
+ text: `Document "${doc_id}" approved. You may proceed with the workflow.`,
23
+ },
24
+ ],
25
+ };
26
+ }
27
+ else {
28
+ return {
29
+ content: [
30
+ {
31
+ type: 'text',
32
+ text: [
33
+ `Document "${doc_id}" rejected.`,
34
+ comment ? `User feedback: ${comment}` : '',
35
+ `Please revise the document based on the feedback and call write_doc again.`,
36
+ ].join('\n'),
37
+ },
38
+ ],
39
+ };
40
+ }
41
+ }
42
+ catch (err) {
43
+ return {
44
+ content: [
45
+ {
46
+ type: 'text',
47
+ text: `Error: ${err instanceof Error ? err.message : String(err)}`,
48
+ },
49
+ ],
50
+ isError: true,
51
+ };
52
+ }
53
+ });
54
+ server.tool('list_pending_reviews', 'List all documents currently pending user review.', {
55
+ project_name: z.string().describe('Project name'),
56
+ }, async ({ project_name }) => {
57
+ const pending = await getPendingReviews(project_name);
58
+ if (pending.length === 0) {
59
+ return {
60
+ content: [
61
+ {
62
+ type: 'text',
63
+ text: 'No documents pending review.',
64
+ },
65
+ ],
66
+ };
67
+ }
68
+ const list = pending.map((r) => `- ${r.docId} (submitted: ${r.submittedAt})`).join('\n');
69
+ return {
70
+ content: [
71
+ {
72
+ type: 'text',
73
+ text: `Documents pending review:\n${list}`,
74
+ },
75
+ ],
76
+ };
77
+ });
78
+ }
79
+ //# sourceMappingURL=approve-doc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approve-doc.js","sourceRoot":"","sources":["../../src/tools/approve-doc.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * MCP Tool: dispatch_role
3
+ *
4
+ * Prepare all data needed to hand off a task to a team member role.
5
+ * Returns: role prompt (with overrides injected), frontmatter config,
6
+ * input documents, task brief, and dispatch tracking info.
7
+ *
8
+ * Automatically:
9
+ * - Creates a dispatch record for tracking
10
+ * - Searches for reusable idle sessions and provides guidance
11
+ *
12
+ * This tool does NOT launch agents — it only prepares the data.
13
+ * The host agent (PM) decides how to pass this to the team member.
14
+ */
15
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
16
+ export declare function registerDispatchRole(server: McpServer, workflowsDir: string): void;