agentic-team 0.0.0-stage → 6.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 +21 -0
- package/README.md +184 -2
- package/bin/build-template.js +208 -0
- package/bin/index.js +1139 -0
- package/package.json +41 -4
- package/template/.claude-plugin/plugin.json +10 -0
- package/template/.orchestra/README.md +401 -0
- package/template/.orchestra/blueprints/README.md +87 -0
- package/template/.orchestra/blueprints/api-only.md +46 -0
- package/template/.orchestra/blueprints/component-crud-resource.md +25 -0
- package/template/.orchestra/blueprints/saas-starter.md +69 -0
- package/template/.orchestra/config.yml +277 -0
- package/template/.orchestra/roles/orchestrator.md +105 -0
- package/template/.orchestra/roles/product-manager.md +438 -0
- package/template/.orchestra/scripts/compact-diff.awk +45 -0
- package/template/.orchestra/stacks/README.md +81 -0
- package/template/.orchestra/stacks/_lib/common.sh +3095 -0
- package/template/.orchestra/stacks/_repo/setup.sh +1109 -0
- package/template/.orchestra/stacks/backend-hono/claude/commands/endpoint.md +13 -0
- package/template/.orchestra/stacks/backend-hono/claude/skills/api-endpoint/SKILL.md +111 -0
- package/template/.orchestra/stacks/backend-hono/claude/skills/testing/SKILL.md +75 -0
- package/template/.orchestra/stacks/backend-hono/setup.sh +5945 -0
- package/template/.orchestra/stacks/backend-hono/stack.md +195 -0
- package/template/.orchestra/stacks/mobile-android-native/claude/commands/component.md +13 -0
- package/template/.orchestra/stacks/mobile-android-native/claude/skills/design-component/SKILL.md +58 -0
- package/template/.orchestra/stacks/mobile-android-native/setup.sh +607 -0
- package/template/.orchestra/stacks/mobile-android-native/stack.md +138 -0
- package/template/.orchestra/stacks/mobile-expo/claude/commands/component.md +12 -0
- package/template/.orchestra/stacks/mobile-expo/claude/skills/design-component/SKILL.md +92 -0
- package/template/.orchestra/stacks/mobile-expo/setup.sh +470 -0
- package/template/.orchestra/stacks/mobile-expo/stack.md +141 -0
- package/template/.orchestra/stacks/mobile-ios-native/claude/commands/component.md +12 -0
- package/template/.orchestra/stacks/mobile-ios-native/claude/skills/design-component/SKILL.md +58 -0
- package/template/.orchestra/stacks/mobile-ios-native/setup.sh +468 -0
- package/template/.orchestra/stacks/mobile-ios-native/stack.md +130 -0
- package/template/.orchestra/stacks/web-nextjs/claude/commands/component.md +12 -0
- package/template/.orchestra/stacks/web-nextjs/claude/skills/design-component/SKILL.md +100 -0
- package/template/.orchestra/stacks/web-nextjs/claude/skills/design-tokens/SKILL.md +61 -0
- package/template/.orchestra/stacks/web-nextjs/setup.sh +128 -0
- package/template/.orchestra/stacks/web-nextjs/stack.md +170 -0
- package/template/.orchestra/stacks/web-vite-react/claude/commands/component.md +12 -0
- package/template/.orchestra/stacks/web-vite-react/claude/skills/design-component/SKILL.md +100 -0
- package/template/.orchestra/stacks/web-vite-react/claude/skills/design-tokens/SKILL.md +61 -0
- package/template/.orchestra/stacks/web-vite-react/setup.sh +185 -0
- package/template/.orchestra/stacks/web-vite-react/stack.md +177 -0
- package/template/.orchestra/trackers/github.sh +467 -0
- package/template/CLAUDE.md +54 -0
- package/template/agents/architect.md +83 -0
- package/template/agents/engineer-high.md +17 -0
- package/template/agents/engineer-low.md +17 -0
- package/template/agents/engineer-max.md +17 -0
- package/template/agents/engineer-medium.md +17 -0
- package/template/agents/engineer-xhigh.md +17 -0
- package/template/agents/lead.md +870 -0
- package/template/agents/milestone-reviewer.md +63 -0
- package/template/agents/orchestrator.md +105 -0
- package/template/agents/product-manager.md +438 -0
- package/template/agents/reviewer.md +301 -0
- package/template/agents/scaffolder.md +180 -0
- package/template/agents/tracker.md +202 -0
- package/template/commands/blueprint.md +23 -0
- package/template/commands/create-role.md +64 -0
- package/template/commands/export.md +45 -0
- package/template/commands/help.md +55 -0
- package/template/commands/hotfix.md +12 -0
- package/template/commands/orchestrator.md +12 -0
- package/template/commands/pm.md +18 -0
- package/template/commands/rewind.md +61 -0
- package/template/commands/setup.md +14 -0
- package/template/commands/start.md +29 -0
- package/template/commands/status.md +11 -0
- package/template/commands/sync.md +73 -0
- package/template/commands/verifier.md +53 -0
- package/template/hooks/audit-context.sh +153 -0
- package/template/hooks/enforce-role.sh +175 -0
- package/template/hooks/protect-system-files.sh +123 -0
- package/template/hooks/review-rounds.sh +172 -0
- package/template/rules/acceptance-check.orchestra.md +11 -0
- package/template/rules/analytics-kpi.orchestra.md +56 -0
- package/template/rules/code-standards.orchestra.md +34 -0
- package/template/rules/comments.orchestra.md +77 -0
- package/template/rules/commit-format.orchestra.md +20 -0
- package/template/rules/dependency-upgrade.orchestra.md +112 -0
- package/template/rules/design-parity.orchestra.md +170 -0
- package/template/rules/observability.orchestra.md +118 -0
- package/template/rules/performance.orchestra.md +186 -0
- package/template/rules/phase-limits.orchestra.md +3 -0
- package/template/rules/pull-request.orchestra.md +213 -0
- package/template/rules/role-boundaries.orchestra.md +117 -0
- package/template/rules/security.orchestra.md +106 -0
- package/template/rules/stuck-detection.orchestra.md +25 -0
- package/template/rules/testing-standards.orchestra.md +214 -0
- package/template/rules/tracker-authority.orchestra.md +190 -0
- package/template/rules/verification-gate.orchestra.md +56 -0
- package/template/skills/accessibility/SKILL.md +31 -0
- package/template/skills/android-testing/SKILL.md +112 -0
- package/template/skills/architecture/SKILL.md +175 -0
- package/template/skills/auth-setup/SKILL.md +105 -0
- package/template/skills/best-practices/SKILL.md +29 -0
- package/template/skills/code-optimizer/SKILL.md +27 -0
- package/template/skills/core-web-vitals/SKILL.md +32 -0
- package/template/skills/crud-api/SKILL.md +32 -0
- package/template/skills/debug/SKILL.md +28 -0
- package/template/skills/deployment/SKILL.md +104 -0
- package/template/skills/error-handling/SKILL.md +154 -0
- package/template/skills/frontend-design/SKILL.md +30 -0
- package/template/skills/fullstack-infrastructure/SKILL.md +108 -0
- package/template/skills/ios-testing/SKILL.md +100 -0
- package/template/skills/mobile-testing/SKILL.md +102 -0
- package/template/skills/observability/SKILL.md +91 -0
- package/template/skills/project-structure/SKILL.md +114 -0
- package/template/skills/push-notifications/SKILL.md +146 -0
- package/template/skills/react-best-practices/SKILL.md +31 -0
- package/template/skills/realtime/SKILL.md +146 -0
- package/template/skills/review/SKILL.md +82 -0
- package/template/skills/testing/SKILL.md +44 -0
- package/template/skills/web-quality-audit/SKILL.md +47 -0
- package/template/skills/web-testing/SKILL.md +120 -0
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
CHANGED
|
@@ -1,3 +1,185 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Orchestra
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
AI team orchestration for [Claude Code](https://docs.anthropic.com/en/docs/claude-code).
|
|
4
|
+
One terminal plans, another builds. You design and decide; the system
|
|
5
|
+
scaffolds, builds, verifies, reviews and delivers.
|
|
6
|
+
|
|
7
|
+
Orchestra is an attempt to clone an engineer into a team of agents. The
|
|
8
|
+
decisions a senior engineer would make — stack, structure, testing shape,
|
|
9
|
+
what a commit looks like, what "done" means — are already encoded, so the
|
|
10
|
+
work comes out the way they would have built it, without them in the loop.
|
|
11
|
+
|
|
12
|
+
No infrastructure. No API keys. Markdown files and Claude Code.
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
In the project:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npx agentic-team
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
That copies `.orchestra/` and `.claude/` in and adds the Orchestra section to
|
|
23
|
+
`CLAUDE.md`. Node 22 or newer. Re-running it upgrades in place — milestones,
|
|
24
|
+
blueprints, your own roles, skills and rules are preserved, and `config.yml`
|
|
25
|
+
is merged rather than overwritten.
|
|
26
|
+
|
|
27
|
+
## How it works
|
|
28
|
+
|
|
29
|
+
Once, in a freshly cloned empty repo:
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
/orchestra:setup
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
It asks what you are building and scaffolds each app from a stack — every
|
|
36
|
+
version resolved from the registry, CI, Dependabot, the PR template, the
|
|
37
|
+
commit hook and the verification gate already in place. Nothing is written
|
|
38
|
+
from memory.
|
|
39
|
+
|
|
40
|
+
Then, for every feature, two terminals:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
Terminal 1 — PM Terminal 2 — Lead
|
|
44
|
+
/orchestra:pm /orchestra:start
|
|
45
|
+
talk the idea through reads the board
|
|
46
|
+
milestones → phases → review design → RFC
|
|
47
|
+
"export" → the board one task → one PR
|
|
48
|
+
/orchestra:sync on your comments reviewer on the PR
|
|
49
|
+
/orchestra:sync on your comments
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The PM writes the plan and gets it reviewed. When you say "export", every
|
|
53
|
+
approved milestone goes to the board in one burst — an epic per milestone, a
|
|
54
|
+
task per phase, all in `backlog`. You move a task to `ready`; lead takes it
|
|
55
|
+
from there and nowhere else.
|
|
56
|
+
|
|
57
|
+
### One task, end to end
|
|
58
|
+
|
|
59
|
+

|
|
60
|
+

|
|
61
|
+
|
|
62
|
+
### The statuses it moves through
|
|
63
|
+
|
|
64
|
+

|
|
65
|
+

|
|
66
|
+
|
|
67
|
+
Two moves are yours: `backlog → ready` and `blocked → ready`. Lead sets the
|
|
68
|
+
rest, and never moves a task to `ready` itself. A re-export updates a task's
|
|
69
|
+
text and never its status.
|
|
70
|
+
|
|
71
|
+
A comment on a task is how you change things. About the plan — scope,
|
|
72
|
+
acceptance criteria, a phase to split — the PM answers it: revises the
|
|
73
|
+
phase, re-exports, replies. About the build — a bug, a design mismatch —
|
|
74
|
+
lead answers it with a pull request. Each surfaces the other's kind and
|
|
75
|
+
stops. Never edit a requirement by hand on the board; the next export
|
|
76
|
+
overwrites it.
|
|
77
|
+
|
|
78
|
+
With `tracker.provider: none` there is no board. The markdown under
|
|
79
|
+
`.orchestra/milestones/` is the source of truth and lead reads it from disk.
|
|
80
|
+
|
|
81
|
+
## Commands
|
|
82
|
+
|
|
83
|
+
| Command | Who | What |
|
|
84
|
+
|---|---|---|
|
|
85
|
+
| `/orchestra:setup` | you, once | Scaffold the repo from stacks |
|
|
86
|
+
| `/orchestra:pm` | you | Open the PM terminal |
|
|
87
|
+
| `/orchestra:start` | you | Open the lead terminal; `--auto` runs unattended and merges its own PRs |
|
|
88
|
+
| `/orchestra:export [id]` | PM, when you ask | Push approved milestones to the board |
|
|
89
|
+
| `/orchestra:sync [id]` | PM or lead | Act on what changed on the board |
|
|
90
|
+
| `/orchestra:status` | PM | Milestone status report |
|
|
91
|
+
| `/orchestra:verifier [N]` | PM | Check built milestones against their requirements |
|
|
92
|
+
| `/orchestra:rewind [N]` | PM | Execution history: decisions, metrics, retries |
|
|
93
|
+
| `/orchestra:hotfix {desc}` | you | Implement → verify → commit → push, fast |
|
|
94
|
+
| `/orchestra:blueprint {name}` | PM | Milestones from a template; `add` saves one |
|
|
95
|
+
| `/orchestra:orchestrator` | you | Maintain the system itself |
|
|
96
|
+
| `/orchestra:create-role` | Orchestrator | A new role, interactively |
|
|
97
|
+
| `/orchestra:help` | anyone | All of the above |
|
|
98
|
+
|
|
99
|
+
## What is inside
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
.orchestra/
|
|
103
|
+
├── config.yml pipeline, verification, testing, delivery, tracker, observability
|
|
104
|
+
├── roles/ product-manager, orchestrator — identity and what each may write
|
|
105
|
+
├── stacks/ how each kind of app is scaffolded and built afterwards
|
|
106
|
+
├── trackers/ the GitHub adapter; ClickUp goes through its MCP connector
|
|
107
|
+
├── blueprints/ milestone templates
|
|
108
|
+
└── milestones/ your work — prd, milestone, phases, tracker.yml, context.md
|
|
109
|
+
|
|
110
|
+
.claude/
|
|
111
|
+
├── agents/ architect, scaffolder, lead, reviewer, tracker
|
|
112
|
+
├── rules/*.orchestra.md discipline, loaded into every session
|
|
113
|
+
├── skills/*/SKILL.md depth on one topic, loaded per phase
|
|
114
|
+
└── commands/orchestra/ the commands above
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**Stacks:** `web-nextjs`, `web-vite-react`, `backend-hono`, `mobile-expo`,
|
|
118
|
+
`mobile-ios-native`, `mobile-android-native`. A defect found while building a
|
|
119
|
+
real project is fixed in the stack, so the next project never meets it.
|
|
120
|
+
|
|
121
|
+
**Rules** are the discipline that applies everywhere: verification gate,
|
|
122
|
+
testing shape, security, performance, observability, commit format, pull
|
|
123
|
+
requests, tracker authority, comments. What a rule can decide mechanically
|
|
124
|
+
is enforced by `scripts/policy-check.mjs` in the gate; the rest is a review
|
|
125
|
+
item, and the reviewer is told which is which.
|
|
126
|
+
|
|
127
|
+
**Roles** write only inside their ownership. PM writes milestones. Lead
|
|
128
|
+
writes `context.md`. Sub-agents write what a phase's scope names. A
|
|
129
|
+
`PreToolUse` hook blocks everything else.
|
|
130
|
+
|
|
131
|
+
## Principles
|
|
132
|
+
|
|
133
|
+
Each one exists because ignoring it produced a real failure.
|
|
134
|
+
|
|
135
|
+
- **Verified, never recalled.** Versions come from the registry, flags from
|
|
136
|
+
`--help`, OWASP settings from the page — at run time.
|
|
137
|
+
- **Determinism over improvisation.** Scaffolding is a script. It runs the
|
|
138
|
+
same way every time and lands in a diff.
|
|
139
|
+
- **Enforcement over advice.** A rule nothing checks is prose. Conventions
|
|
140
|
+
are backed by CI, hooks, coverage gates and a policy script.
|
|
141
|
+
- **A green suite is the merge signal.** Everything wrapping a third-party
|
|
142
|
+
library has a test, so a dependency bump that changes behaviour turns red.
|
|
143
|
+
- **One source of truth.** `tracker.provider` names it. Never both.
|
|
144
|
+
- **Measure before building.** A milestone states its metric, baseline,
|
|
145
|
+
target and how it is read — or it is not ready.
|
|
146
|
+
- **Report honestly.** Say what was verified and what was assumed. Unverified
|
|
147
|
+
is a word.
|
|
148
|
+
|
|
149
|
+
## Upgrading
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
npx agentic-team@latest
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
| What | On upgrade |
|
|
156
|
+
|---|---|
|
|
157
|
+
| Roles, rules, agents, commands, stacks, shipped skills | Updated |
|
|
158
|
+
| Your own roles, skills, rules | Preserved |
|
|
159
|
+
| Blueprints (shipped / yours) | Updated / preserved |
|
|
160
|
+
| `milestones/` | Untouched |
|
|
161
|
+
| `config.yml` | Merged — your values kept, new keys added |
|
|
162
|
+
|
|
163
|
+
## Documentation
|
|
164
|
+
|
|
165
|
+
- [Getting started](docs/getting-started.md)
|
|
166
|
+
- [Commands](docs/commands.md)
|
|
167
|
+
- [Roles](docs/roles.md)
|
|
168
|
+
- [Features](docs/features.md)
|
|
169
|
+
- [Stacks](docs/stacks.md)
|
|
170
|
+
- [Skills](docs/skills.md)
|
|
171
|
+
- [Blueprints](docs/blueprints.md)
|
|
172
|
+
|
|
173
|
+
## Development
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
yarn test
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
`bin/index.js` is the installer. `template/` is built from `.orchestra/` and
|
|
180
|
+
`.claude/` by `yarn template`, is gitignored, and is regenerated on every
|
|
181
|
+
publish. Pre-commit runs the template build and the suite.
|
|
182
|
+
|
|
183
|
+
## License
|
|
184
|
+
|
|
185
|
+
MIT
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require("node:fs");
|
|
4
|
+
const path = require("node:path");
|
|
5
|
+
|
|
6
|
+
const rootDir = process.cwd();
|
|
7
|
+
|
|
8
|
+
// Output directory, `template/` unless told otherwise.
|
|
9
|
+
//
|
|
10
|
+
// The suite reads template/ from several files while build-template.test.js
|
|
11
|
+
// rebuilds it, and copyFileSync truncates before it writes — so a reader could
|
|
12
|
+
// catch a file mid-write and fail for a reason that had nothing to do with it.
|
|
13
|
+
// The test builds into a directory of its own instead of racing on the shared
|
|
14
|
+
// one.
|
|
15
|
+
const outFlag = process.argv.indexOf("--out");
|
|
16
|
+
const templateDir =
|
|
17
|
+
outFlag !== -1 && process.argv[outFlag + 1]
|
|
18
|
+
? path.resolve(process.argv[outFlag + 1])
|
|
19
|
+
: path.join(rootDir, "template");
|
|
20
|
+
|
|
21
|
+
// Dev-only agents that should NOT be published to users
|
|
22
|
+
const DEV_ONLY_AGENTS = new Set([
|
|
23
|
+
"codebase-deep-analyzer.md",
|
|
24
|
+
"orchestra-analyzer.md",
|
|
25
|
+
"orchestra-reviewer.md",
|
|
26
|
+
"repo-deep-analyzer.md",
|
|
27
|
+
]);
|
|
28
|
+
|
|
29
|
+
// Dev-only skills that should NOT be published to users
|
|
30
|
+
const DEV_ONLY_SKILLS = new Set(["ship"]);
|
|
31
|
+
|
|
32
|
+
// Plugin manifest
|
|
33
|
+
const PLUGIN_MANIFEST = {
|
|
34
|
+
name: "orchestra",
|
|
35
|
+
description:
|
|
36
|
+
"AI Team Orchestration — multi-role coordination with milestones, phases, and quality gates for Claude Code",
|
|
37
|
+
version: require("../package.json").version,
|
|
38
|
+
author: { name: "Sulhadin Öney" },
|
|
39
|
+
repository: "https://github.com/sulhadin/orchestrator",
|
|
40
|
+
license: "MIT",
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// System files to include in the template (plugin-compatible structure)
|
|
44
|
+
// Plugin dirs (agents/, commands/, skills/, rules/) go at root level
|
|
45
|
+
// .orchestra/ and CLAUDE.md also go at root level
|
|
46
|
+
const SYSTEM_PATHS = [
|
|
47
|
+
{ src: ".claude/agents", dest: "agents", filter: (f) => !DEV_ONLY_AGENTS.has(f) },
|
|
48
|
+
{ src: ".claude/commands/orchestra", dest: "commands" },
|
|
49
|
+
{ src: ".claude/rules", dest: "rules", filter: (f) => f.endsWith(".orchestra.md") },
|
|
50
|
+
{
|
|
51
|
+
src: ".claude/skills",
|
|
52
|
+
dest: "skills",
|
|
53
|
+
filter: (f) => {
|
|
54
|
+
if (DEV_ONLY_SKILLS.has(f)) return false;
|
|
55
|
+
const skillDir = path.join(rootDir, ".claude/skills", f);
|
|
56
|
+
return fs.statSync(skillDir).isDirectory() && fs.existsSync(path.join(skillDir, "SKILL.md"));
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
// A hook is only enforcement if it ships and is registered. Without both
|
|
60
|
+
// it is a script nobody runs, which is the failure mode the rules exist to
|
|
61
|
+
// avoid.
|
|
62
|
+
{ src: ".claude/hooks", dest: "hooks" },
|
|
63
|
+
// Same reasoning as the hook above: an adapter that does not ship is a
|
|
64
|
+
// script nobody runs, and the tracker agent would be back to improvising
|
|
65
|
+
// GraphQL in a prompt.
|
|
66
|
+
{ src: ".orchestra/trackers", dest: ".orchestra/trackers" },
|
|
67
|
+
// A rule that names a script the project does not have is prose nobody can
|
|
68
|
+
// follow. pull-request.orchestra.md points reviewers at this directory.
|
|
69
|
+
// The repo's own scripts/ stays home: compact-test-output.awk parses
|
|
70
|
+
// `node --test`, and scaffolded apps run vitest or jest.
|
|
71
|
+
{ src: ".orchestra/scripts", dest: ".orchestra/scripts" },
|
|
72
|
+
{ src: ".orchestra/roles", dest: ".orchestra/roles" },
|
|
73
|
+
{ src: ".orchestra/blueprints", dest: ".orchestra/blueprints" },
|
|
74
|
+
{ src: ".orchestra/stacks", dest: ".orchestra/stacks" },
|
|
75
|
+
{ src: ".orchestra/config.yml", dest: ".orchestra/config.yml" },
|
|
76
|
+
{ src: ".orchestra/README.md", dest: ".orchestra/README.md" },
|
|
77
|
+
// CLAUDE.md is handled separately — only the marked section may ship.
|
|
78
|
+
];
|
|
79
|
+
|
|
80
|
+
// The repo's CLAUDE.md carries a "## Development" section about THIS package.
|
|
81
|
+
// Copying it wholesale means every scaffolded project tells its own agents it
|
|
82
|
+
// is the orchestrator npm package. Ship only what is between the markers.
|
|
83
|
+
function packClaudeMd() {
|
|
84
|
+
const src = fs.readFileSync(path.join(rootDir, "CLAUDE.md"), "utf-8");
|
|
85
|
+
const start = src.indexOf("<!-- orchestra -->");
|
|
86
|
+
const end = src.indexOf("<!-- /orchestra -->");
|
|
87
|
+
if (start === -1 || end === -1) {
|
|
88
|
+
throw new Error("CLAUDE.md is missing the <!-- orchestra --> markers");
|
|
89
|
+
}
|
|
90
|
+
const section = src.slice(start, end + "<!-- /orchestra -->".length);
|
|
91
|
+
const header =
|
|
92
|
+
"# CLAUDE.md\n\n" +
|
|
93
|
+
"This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n";
|
|
94
|
+
const claudeMd = path.join(templateDir, "CLAUDE.md");
|
|
95
|
+
fs.writeFileSync(claudeMd, `${header + section}\n`);
|
|
96
|
+
record(claudeMd);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Every path this run wrote. What is not in here at the end is retired.
|
|
101
|
+
*
|
|
102
|
+
* The builder only ever copied, so a file this project stopped shipping
|
|
103
|
+
* survived in template/ forever and went out in the package — jira.sh
|
|
104
|
+
* outlived its own deletion by a whole release.
|
|
105
|
+
*
|
|
106
|
+
* Pruning afterwards rather than wiping first, because template/ is read by
|
|
107
|
+
* the suite: deleting it up front leaves a window where a parallel test file
|
|
108
|
+
* finds no template at all, which is a flake that looks like a real failure.
|
|
109
|
+
*/
|
|
110
|
+
const written = new Set();
|
|
111
|
+
function record(fullPath) {
|
|
112
|
+
written.add(path.resolve(fullPath));
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function ensureDir(dir) {
|
|
116
|
+
if (!fs.existsSync(dir)) {
|
|
117
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function copyRecursive(src, dest, filter = null) {
|
|
122
|
+
const fullSrc = path.join(rootDir, src);
|
|
123
|
+
const fullDest = path.join(templateDir, dest);
|
|
124
|
+
|
|
125
|
+
if (!fs.existsSync(fullSrc)) {
|
|
126
|
+
console.warn(` [!] Source not found, skipping: ${src}`);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const stat = fs.statSync(fullSrc);
|
|
131
|
+
|
|
132
|
+
if (stat.isDirectory()) {
|
|
133
|
+
ensureDir(fullDest);
|
|
134
|
+
const entries = fs.readdirSync(fullSrc, { withFileTypes: true });
|
|
135
|
+
|
|
136
|
+
for (const entry of entries) {
|
|
137
|
+
if (filter && !filter(entry.name)) continue;
|
|
138
|
+
|
|
139
|
+
const entrySrc = path.join(src, entry.name);
|
|
140
|
+
const entryDest = path.join(dest, entry.name);
|
|
141
|
+
|
|
142
|
+
const fullEntrySrc = path.join(rootDir, entrySrc);
|
|
143
|
+
const fullEntryDest = path.join(templateDir, entryDest);
|
|
144
|
+
|
|
145
|
+
if (entry.isSymbolicLink()) {
|
|
146
|
+
// Dereference. The source repo uses symlinks to keep one source of
|
|
147
|
+
// truth, but npm pack silently DROPS symlinks from the tarball —
|
|
148
|
+
// shipping them means the agent simply does not exist for users.
|
|
149
|
+
const resolved = fs.realpathSync(fullEntrySrc);
|
|
150
|
+
if (fs.existsSync(fullEntryDest)) fs.unlinkSync(fullEntryDest);
|
|
151
|
+
fs.copyFileSync(resolved, fullEntryDest);
|
|
152
|
+
record(fullEntryDest);
|
|
153
|
+
} else if (entry.isDirectory()) {
|
|
154
|
+
copyRecursive(entrySrc, entryDest);
|
|
155
|
+
} else {
|
|
156
|
+
fs.copyFileSync(fullEntrySrc, fullEntryDest);
|
|
157
|
+
record(fullEntryDest);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
} else {
|
|
161
|
+
ensureDir(path.dirname(fullDest));
|
|
162
|
+
fs.copyFileSync(fullSrc, fullDest);
|
|
163
|
+
record(fullDest);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
console.log("\n Orchestra — Template Builder");
|
|
168
|
+
console.log(" Packing root system files into template/...\n");
|
|
169
|
+
|
|
170
|
+
for (const item of SYSTEM_PATHS) {
|
|
171
|
+
copyRecursive(item.src, item.dest, item.filter);
|
|
172
|
+
console.log(` [+] Packed: ${item.src}`);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
packClaudeMd();
|
|
176
|
+
console.log(" [+] Packed: CLAUDE.md (orchestra section only)");
|
|
177
|
+
|
|
178
|
+
// Write plugin manifest
|
|
179
|
+
const pluginDir = path.join(templateDir, ".claude-plugin");
|
|
180
|
+
ensureDir(pluginDir);
|
|
181
|
+
const manifestPath = path.join(pluginDir, "plugin.json");
|
|
182
|
+
fs.writeFileSync(manifestPath, `${JSON.stringify(PLUGIN_MANIFEST, null, 2)}\n`);
|
|
183
|
+
record(manifestPath);
|
|
184
|
+
console.log(" [+] Generated .claude-plugin/plugin.json");
|
|
185
|
+
|
|
186
|
+
// Retire what this run did not write. A file removed from the source is
|
|
187
|
+
// removed from the package in the same commit, rather than shipping until
|
|
188
|
+
// somebody notices.
|
|
189
|
+
let retired = 0;
|
|
190
|
+
function prune(dir) {
|
|
191
|
+
if (!fs.existsSync(dir)) return;
|
|
192
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
193
|
+
const full = path.join(dir, entry.name);
|
|
194
|
+
if (entry.isDirectory()) {
|
|
195
|
+
prune(full);
|
|
196
|
+
if (fs.readdirSync(full).length === 0) fs.rmdirSync(full);
|
|
197
|
+
} else if (!written.has(path.resolve(full))) {
|
|
198
|
+
fs.unlinkSync(full);
|
|
199
|
+
console.log(` [-] Retired: ${path.relative(templateDir, full)}`);
|
|
200
|
+
retired++;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
prune(templateDir);
|
|
205
|
+
if (retired === 0) console.log(" [=] Nothing to retire");
|
|
206
|
+
|
|
207
|
+
console.log("\n Done! Template is updated and ready for release.");
|
|
208
|
+
console.log(" Run 'yarn test' to verify.\n");
|