@sulhadin/orchestrator 1.1.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sulhadin Öney
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,208 @@
1
+ # Orchestra
2
+
3
+ A milestone-based orchestration system for [Claude Code](https://docs.anthropic.com/en/docs/claude-code). One terminal, one PM, one worker agent — features built end-to-end without manual role switching.
4
+
5
+ ## The Problem
6
+
7
+ Building a feature with Claude Code typically looks like this:
8
+
9
+ ```
10
+ You: "Build user authentication"
11
+ You: *opens terminal* "@architect — design the system"
12
+ You: *reads RFC, approves*
13
+ You: *opens terminal* "@backend — implement the API"
14
+ You: *opens terminal* "@reviewer — review the code"
15
+ You: *opens terminal* "@pm — close the feature"
16
+ ```
17
+
18
+ You become the orchestrator. You carry context between sessions, sequence work in the right order, and manage the pipeline manually. This is tedious and error-prone.
19
+
20
+ ## The Solution
21
+
22
+ Orchestra turns Claude Code's PM role into an autonomous orchestrator. You describe what you want, PM handles the rest:
23
+
24
+ ```
25
+ You: "@pm"
26
+ You: "I want user authentication with JWT"
27
+ PM: creates milestone, grooms phases, dispatches worker agent
28
+ @architect writes RFC → you approve
29
+ @backend implements phase by phase → each phase = one commit
30
+ @frontend builds the UI → each phase = one commit
31
+ @reviewer reviews unpushed commits
32
+ you approve → PM pushes to origin
33
+ milestone closed.
34
+ ```
35
+
36
+ One conversation. One terminal. PM drives everything.
37
+
38
+ ## How It Works
39
+
40
+ ```
41
+ You ←→ PM (always-on orchestrator)
42
+
43
+ ├── Creates milestone with groomed phases
44
+ ├── Spawns one worker agent (all roles loaded)
45
+
46
+ ├── SendMessage("@architect: write RFC") → awaits
47
+ ├── SendMessage("@backend: phase-1") → awaits → commit
48
+ ├── SendMessage("@backend: phase-2") → awaits → commit
49
+ ├── SendMessage("@frontend: phase-3") → awaits → commit
50
+ ├── SendMessage("@reviewer: review") → awaits
51
+
52
+ ├── You approve → PM pushes to origin
53
+ └── Milestone closed
54
+ ```
55
+
56
+ ### Key Concepts
57
+
58
+ **Milestones** — Each feature is a milestone. Everything lives in one directory:
59
+
60
+ ```
61
+ .orchestra/milestones/M1-user-auth/
62
+ ├── prd.md PM writes (what + why)
63
+ ├── milestone.md Status, acceptance criteria
64
+ ├── grooming.md Discussion notes, decisions
65
+ ├── rfc.md Architect writes (how)
66
+ ├── architecture.md Architect writes (system design)
67
+ ├── design.md Frontend engineer writes (UI/UX)
68
+ ├── adrs/ Architecture Decision Records
69
+ └── phases/
70
+ ├── phase-1.md backend: DB schema → commit
71
+ ├── phase-2.md backend: API endpoints → commit
72
+ └── phase-3.md frontend: login UI → commit
73
+ ```
74
+
75
+ **Single Worker Session** — PM creates one agent with all roles loaded. No warmup on role switches. Architect decisions are in context when backend implements. Backend code is in context when reviewer reviews.
76
+
77
+ **Await-Based** — PM dispatches via `SendMessage`, blocks until the worker returns. No polling, no signal files. Results flow directly through the return value.
78
+
79
+ **Git-Native Review** — Reviewer doesn't need task files. Reviews unpushed commits on the current branch via `git diff origin/branch...HEAD`.
80
+
81
+ ### Roles
82
+
83
+ | Role | What it does |
84
+ |------|-------------|
85
+ | **Product Manager** | Orchestrates everything. Creates milestones, dispatches worker, drives pipeline. |
86
+ | **Architect** | Designs technical solutions. Writes RFCs, ADRs. |
87
+ | **Backend Engineer** | Implements backend code + tests. One commit per phase. |
88
+ | **Frontend Engineer** | Designs + implements UI. One commit per phase. |
89
+ | **Code Reviewer** | Reviews unpushed commits. Returns approved or changes-requested. |
90
+ | **Owner** | Maintains Orchestra system files (roles, rules, structure). |
91
+
92
+ ### Pipeline
93
+
94
+ ```
95
+ PM creates milestone
96
+ → Architect writes RFC
97
+ → [You approve RFC]
98
+ → Backend phases (sequential, each → commit)
99
+ → Frontend phases (sequential, each → commit)
100
+ → Reviewer reviews unpushed commits
101
+ → Fix cycle if needed (one round, no re-review)
102
+ → [You approve push]
103
+ → PM pushes to origin, closes milestone
104
+ ```
105
+
106
+ ### Approval Gates
107
+
108
+ You only need to approve twice:
109
+
110
+ 1. **RFC → Implementation** — after architect writes the technical design
111
+ 2. **Push to origin** — after reviewer approves
112
+
113
+ Everything else is automatic.
114
+
115
+ ## Install
116
+
117
+ ```bash
118
+ npx @sulhadin/orchestrator
119
+ ```
120
+
121
+ This will:
122
+
123
+ - Copy `.orchestra/` directory to your project root
124
+ - Create `CLAUDE.md` if it doesn't exist, or append Orchestra instructions to your existing one
125
+
126
+ ### What Gets Installed
127
+
128
+ ```
129
+ your-project/
130
+ ├── .orchestra/
131
+ │ ├── README.md Orchestration rules
132
+ │ ├── agents/worker.md Worker agent prompt
133
+ │ ├── roles/ 6 role definitions
134
+ │ ├── milestones/ Feature work (empty)
135
+
136
+ └── CLAUDE.md Orchestra instructions for Claude
137
+ ```
138
+
139
+ ## Usage
140
+
141
+ Open Claude Code in your project and say `@pm`:
142
+
143
+ ```
144
+ You: @pm
145
+ PM: "No active milestones. Ready for instructions."
146
+
147
+ You: "I want to add a health check endpoint"
148
+ PM: *discusses scope, challenges assumptions, proposes approach*
149
+
150
+ You: "Let's build it"
151
+ PM: *creates milestone, grooms phases, dispatches worker*
152
+ *reports progress after each phase*
153
+ *asks for approval at gates*
154
+ *pushes and closes milestone*
155
+ ```
156
+
157
+ ### Commands
158
+
159
+ | Command | Description |
160
+ |---------|------------|
161
+ | `@pm` | Activate Product Manager |
162
+ | `@backend` | Activate Backend Engineer (manual mode) |
163
+ | `@frontend` | Activate Frontend Engineer (manual mode) |
164
+ | `@reviewer` | Activate Code Reviewer (manual mode) |
165
+ | `@architect` | Activate Architect (manual mode) |
166
+ | `@owner` | Activate Owner (system maintenance) |
167
+ | `status` | Pipeline status report (PM only) |
168
+ | `orc help` | Show all commands |
169
+
170
+ ### Manual Mode
171
+
172
+ You can still use roles directly without PM orchestration:
173
+
174
+ ```
175
+ You: @backend
176
+ BE: *checks milestones for pending backend phases*
177
+ *starts working*
178
+ ```
179
+
180
+ Autonomous and manual modes work side by side.
181
+
182
+ ## Engineering Standards
183
+
184
+ Orchestra enforces these through role definitions and code review:
185
+
186
+ - **SOLID, KISS, YAGNI, DRY** — enforced by reviewer
187
+ - **Code without tests is not done** — backend and frontend engineers write tests as part of implementation
188
+ - **Conventional commits** — one commit per phase (`feat`, `fix`, `refactor`, etc.)
189
+ - **No `any` types, no unused code, no workarounds** — zero-tolerance rules
190
+ - **Design before code** — frontend engineer writes design specs before implementing
191
+ - **Grooming before implementation** — detailed phase planning before any code is written
192
+ - **Current library versions** — always verify with docs, never rely on memory
193
+
194
+ ## Configuration
195
+
196
+ Customize roles by editing files in `.orchestra/roles/`. Each role file defines:
197
+
198
+ - Identity and boundaries
199
+ - File ownership (what it can/cannot write)
200
+ - Workflow steps
201
+ - Engineering principles
202
+ - Review checklists (for code-reviewer)
203
+
204
+ The worker agent prompt (`.orchestra/agents/worker.md`) controls how the subagent behaves when PM dispatches it.
205
+
206
+ ## License
207
+
208
+ MIT
package/bin/index.js ADDED
@@ -0,0 +1,163 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+
6
+ const targetDir = process.cwd();
7
+ const templateDir = path.join(__dirname, "..", "template");
8
+
9
+ const ORCHESTRA_SECTION_START = "<!-- orchestra -->";
10
+ const ORCHESTRA_SECTION_END = "<!-- /orchestra -->";
11
+
12
+ const USER_DIRS = ["milestones"];
13
+
14
+ function copyDirRecursive(src, dest) {
15
+ if (!fs.existsSync(dest)) {
16
+ fs.mkdirSync(dest, { recursive: true });
17
+ }
18
+
19
+ const entries = fs.readdirSync(src, { withFileTypes: true });
20
+
21
+ for (const entry of entries) {
22
+ const srcPath = path.join(src, entry.name);
23
+ const destPath = path.join(dest, entry.name);
24
+
25
+ if (entry.isDirectory()) {
26
+ copyDirRecursive(srcPath, destPath);
27
+ } else {
28
+ fs.copyFileSync(srcPath, destPath);
29
+ }
30
+ }
31
+ }
32
+
33
+ function rmDirRecursive(dir) {
34
+ if (!fs.existsSync(dir)) return;
35
+
36
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
37
+
38
+ for (const entry of entries) {
39
+ const fullPath = path.join(dir, entry.name);
40
+ if (entry.isDirectory()) {
41
+ rmDirRecursive(fullPath);
42
+ } else {
43
+ fs.unlinkSync(fullPath);
44
+ }
45
+ }
46
+
47
+ fs.rmdirSync(dir);
48
+ }
49
+
50
+ function extractOrchestraSection(content) {
51
+ const startIdx = content.indexOf(ORCHESTRA_SECTION_START);
52
+ if (startIdx === -1) return null;
53
+
54
+ const endIdx = content.indexOf(ORCHESTRA_SECTION_END, startIdx);
55
+ if (endIdx === -1) {
56
+ return content.slice(startIdx);
57
+ }
58
+ return content.slice(startIdx, endIdx + ORCHESTRA_SECTION_END.length);
59
+ }
60
+
61
+ function run() {
62
+ console.log("");
63
+ console.log(" Orchestra — AI Team Orchestration");
64
+ console.log(" Installing into: " + targetDir);
65
+ console.log("");
66
+
67
+ const orchestraSrc = path.join(templateDir, ".orchestra");
68
+ const orchestraDest = path.join(targetDir, ".orchestra");
69
+ const isUpgrade = fs.existsSync(orchestraDest);
70
+
71
+ if (isUpgrade) {
72
+ // Backup user data directories
73
+ const backups = {};
74
+
75
+ for (const dir of USER_DIRS) {
76
+ const dirPath = path.join(orchestraDest, dir);
77
+ const backupPath = path.join(targetDir, ".orchestra-backup-" + dir);
78
+
79
+ if (fs.existsSync(dirPath)) {
80
+ // Check if directory has real content (not just .gitkeep)
81
+ const files = fs.readdirSync(dirPath).filter((f) => f !== ".gitkeep");
82
+ if (files.length > 0) {
83
+ copyDirRecursive(dirPath, backupPath);
84
+ backups[dir] = backupPath;
85
+ console.log(" [~] Backed up " + dir + "/ (" + files.length + " items)");
86
+ }
87
+ }
88
+ }
89
+
90
+ // Remove old .orchestra/
91
+ rmDirRecursive(orchestraDest);
92
+ console.log(" [~] Removed old .orchestra/");
93
+
94
+ // Copy fresh .orchestra/
95
+ copyDirRecursive(orchestraSrc, orchestraDest);
96
+ console.log(" [+] .orchestra/ installed (clean)");
97
+
98
+ // Restore user data
99
+ for (const [dir, backupPath] of Object.entries(backups)) {
100
+ const restorePath = path.join(orchestraDest, dir);
101
+
102
+ // Remove the template's empty dir first
103
+ if (fs.existsSync(restorePath)) {
104
+ rmDirRecursive(restorePath);
105
+ }
106
+
107
+ copyDirRecursive(backupPath, restorePath);
108
+ rmDirRecursive(backupPath);
109
+ console.log(" [+] Restored " + dir + "/");
110
+ }
111
+ } else {
112
+ // Fresh install
113
+ copyDirRecursive(orchestraSrc, orchestraDest);
114
+ console.log(" [+] .orchestra/ installed");
115
+ }
116
+
117
+ // Handle CLAUDE.md
118
+ const templateClaudeMd = fs.readFileSync(
119
+ path.join(templateDir, "CLAUDE.md"),
120
+ "utf-8"
121
+ );
122
+ const targetClaudeMdPath = path.join(targetDir, "CLAUDE.md");
123
+
124
+ if (fs.existsSync(targetClaudeMdPath)) {
125
+ let existingContent = fs.readFileSync(targetClaudeMdPath, "utf-8");
126
+ const orchestraSection = extractOrchestraSection(templateClaudeMd);
127
+
128
+ if (!orchestraSection) {
129
+ console.log(" [!] Could not extract Orchestra section from template");
130
+ return;
131
+ }
132
+
133
+ if (existingContent.includes(ORCHESTRA_SECTION_START)) {
134
+ const existingSection = extractOrchestraSection(existingContent);
135
+ if (existingSection) {
136
+ existingContent = existingContent.replace(
137
+ existingSection,
138
+ orchestraSection
139
+ );
140
+ }
141
+ console.log(" [~] CLAUDE.md updated (Orchestra section replaced)");
142
+ } else {
143
+ existingContent =
144
+ existingContent.trimEnd() + "\n\n" + orchestraSection + "\n";
145
+ console.log(" [+] CLAUDE.md updated (Orchestra section appended)");
146
+ }
147
+
148
+ fs.writeFileSync(targetClaudeMdPath, existingContent);
149
+ } else {
150
+ fs.copyFileSync(path.join(templateDir, "CLAUDE.md"), targetClaudeMdPath);
151
+ console.log(" [+] CLAUDE.md created");
152
+ }
153
+
154
+ console.log("");
155
+ console.log(" Done! Orchestra is ready.");
156
+ console.log("");
157
+ console.log(" Next steps:");
158
+ console.log(" 1. Open Claude Code in your project");
159
+ console.log(' 2. Say "@pm" to start orchestrating');
160
+ console.log("");
161
+ }
162
+
163
+ run();
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@sulhadin/orchestrator",
3
+ "version": "1.1.0",
4
+ "description": "AI Team Orchestration System — multi-role coordination for Claude Code",
5
+ "bin": {
6
+ "orchestrator": "bin/index.js"
7
+ },
8
+ "files": [
9
+ "bin/",
10
+ "template/"
11
+ ],
12
+ "keywords": [
13
+ "claude",
14
+ "orchestrator",
15
+ "ai",
16
+ "agent",
17
+ "multi-agent",
18
+ "claude-code"
19
+ ],
20
+ "author": "Sulhadin Öney",
21
+ "license": "MIT",
22
+ "packageManager": "yarn@4.13.0"
23
+ }