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.
Files changed (118) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +184 -2
  3. package/bin/build-template.js +208 -0
  4. package/bin/index.js +1139 -0
  5. package/package.json +41 -4
  6. package/template/.claude-plugin/plugin.json +10 -0
  7. package/template/.orchestra/README.md +401 -0
  8. package/template/.orchestra/blueprints/README.md +87 -0
  9. package/template/.orchestra/blueprints/api-only.md +46 -0
  10. package/template/.orchestra/blueprints/component-crud-resource.md +25 -0
  11. package/template/.orchestra/blueprints/saas-starter.md +69 -0
  12. package/template/.orchestra/config.yml +277 -0
  13. package/template/.orchestra/roles/orchestrator.md +105 -0
  14. package/template/.orchestra/roles/product-manager.md +438 -0
  15. package/template/.orchestra/scripts/compact-diff.awk +45 -0
  16. package/template/.orchestra/stacks/README.md +81 -0
  17. package/template/.orchestra/stacks/_lib/common.sh +3095 -0
  18. package/template/.orchestra/stacks/_repo/setup.sh +1109 -0
  19. package/template/.orchestra/stacks/backend-hono/claude/commands/endpoint.md +13 -0
  20. package/template/.orchestra/stacks/backend-hono/claude/skills/api-endpoint/SKILL.md +111 -0
  21. package/template/.orchestra/stacks/backend-hono/claude/skills/testing/SKILL.md +75 -0
  22. package/template/.orchestra/stacks/backend-hono/setup.sh +5945 -0
  23. package/template/.orchestra/stacks/backend-hono/stack.md +195 -0
  24. package/template/.orchestra/stacks/mobile-android-native/claude/commands/component.md +13 -0
  25. package/template/.orchestra/stacks/mobile-android-native/claude/skills/design-component/SKILL.md +58 -0
  26. package/template/.orchestra/stacks/mobile-android-native/setup.sh +607 -0
  27. package/template/.orchestra/stacks/mobile-android-native/stack.md +138 -0
  28. package/template/.orchestra/stacks/mobile-expo/claude/commands/component.md +12 -0
  29. package/template/.orchestra/stacks/mobile-expo/claude/skills/design-component/SKILL.md +92 -0
  30. package/template/.orchestra/stacks/mobile-expo/setup.sh +470 -0
  31. package/template/.orchestra/stacks/mobile-expo/stack.md +141 -0
  32. package/template/.orchestra/stacks/mobile-ios-native/claude/commands/component.md +12 -0
  33. package/template/.orchestra/stacks/mobile-ios-native/claude/skills/design-component/SKILL.md +58 -0
  34. package/template/.orchestra/stacks/mobile-ios-native/setup.sh +468 -0
  35. package/template/.orchestra/stacks/mobile-ios-native/stack.md +130 -0
  36. package/template/.orchestra/stacks/web-nextjs/claude/commands/component.md +12 -0
  37. package/template/.orchestra/stacks/web-nextjs/claude/skills/design-component/SKILL.md +100 -0
  38. package/template/.orchestra/stacks/web-nextjs/claude/skills/design-tokens/SKILL.md +61 -0
  39. package/template/.orchestra/stacks/web-nextjs/setup.sh +128 -0
  40. package/template/.orchestra/stacks/web-nextjs/stack.md +170 -0
  41. package/template/.orchestra/stacks/web-vite-react/claude/commands/component.md +12 -0
  42. package/template/.orchestra/stacks/web-vite-react/claude/skills/design-component/SKILL.md +100 -0
  43. package/template/.orchestra/stacks/web-vite-react/claude/skills/design-tokens/SKILL.md +61 -0
  44. package/template/.orchestra/stacks/web-vite-react/setup.sh +185 -0
  45. package/template/.orchestra/stacks/web-vite-react/stack.md +177 -0
  46. package/template/.orchestra/trackers/github.sh +467 -0
  47. package/template/CLAUDE.md +54 -0
  48. package/template/agents/architect.md +83 -0
  49. package/template/agents/engineer-high.md +17 -0
  50. package/template/agents/engineer-low.md +17 -0
  51. package/template/agents/engineer-max.md +17 -0
  52. package/template/agents/engineer-medium.md +17 -0
  53. package/template/agents/engineer-xhigh.md +17 -0
  54. package/template/agents/lead.md +870 -0
  55. package/template/agents/milestone-reviewer.md +63 -0
  56. package/template/agents/orchestrator.md +105 -0
  57. package/template/agents/product-manager.md +438 -0
  58. package/template/agents/reviewer.md +301 -0
  59. package/template/agents/scaffolder.md +180 -0
  60. package/template/agents/tracker.md +202 -0
  61. package/template/commands/blueprint.md +23 -0
  62. package/template/commands/create-role.md +64 -0
  63. package/template/commands/export.md +45 -0
  64. package/template/commands/help.md +55 -0
  65. package/template/commands/hotfix.md +12 -0
  66. package/template/commands/orchestrator.md +12 -0
  67. package/template/commands/pm.md +18 -0
  68. package/template/commands/rewind.md +61 -0
  69. package/template/commands/setup.md +14 -0
  70. package/template/commands/start.md +29 -0
  71. package/template/commands/status.md +11 -0
  72. package/template/commands/sync.md +73 -0
  73. package/template/commands/verifier.md +53 -0
  74. package/template/hooks/audit-context.sh +153 -0
  75. package/template/hooks/enforce-role.sh +175 -0
  76. package/template/hooks/protect-system-files.sh +123 -0
  77. package/template/hooks/review-rounds.sh +172 -0
  78. package/template/rules/acceptance-check.orchestra.md +11 -0
  79. package/template/rules/analytics-kpi.orchestra.md +56 -0
  80. package/template/rules/code-standards.orchestra.md +34 -0
  81. package/template/rules/comments.orchestra.md +77 -0
  82. package/template/rules/commit-format.orchestra.md +20 -0
  83. package/template/rules/dependency-upgrade.orchestra.md +112 -0
  84. package/template/rules/design-parity.orchestra.md +170 -0
  85. package/template/rules/observability.orchestra.md +118 -0
  86. package/template/rules/performance.orchestra.md +186 -0
  87. package/template/rules/phase-limits.orchestra.md +3 -0
  88. package/template/rules/pull-request.orchestra.md +213 -0
  89. package/template/rules/role-boundaries.orchestra.md +117 -0
  90. package/template/rules/security.orchestra.md +106 -0
  91. package/template/rules/stuck-detection.orchestra.md +25 -0
  92. package/template/rules/testing-standards.orchestra.md +214 -0
  93. package/template/rules/tracker-authority.orchestra.md +190 -0
  94. package/template/rules/verification-gate.orchestra.md +56 -0
  95. package/template/skills/accessibility/SKILL.md +31 -0
  96. package/template/skills/android-testing/SKILL.md +112 -0
  97. package/template/skills/architecture/SKILL.md +175 -0
  98. package/template/skills/auth-setup/SKILL.md +105 -0
  99. package/template/skills/best-practices/SKILL.md +29 -0
  100. package/template/skills/code-optimizer/SKILL.md +27 -0
  101. package/template/skills/core-web-vitals/SKILL.md +32 -0
  102. package/template/skills/crud-api/SKILL.md +32 -0
  103. package/template/skills/debug/SKILL.md +28 -0
  104. package/template/skills/deployment/SKILL.md +104 -0
  105. package/template/skills/error-handling/SKILL.md +154 -0
  106. package/template/skills/frontend-design/SKILL.md +30 -0
  107. package/template/skills/fullstack-infrastructure/SKILL.md +108 -0
  108. package/template/skills/ios-testing/SKILL.md +100 -0
  109. package/template/skills/mobile-testing/SKILL.md +102 -0
  110. package/template/skills/observability/SKILL.md +91 -0
  111. package/template/skills/project-structure/SKILL.md +114 -0
  112. package/template/skills/push-notifications/SKILL.md +146 -0
  113. package/template/skills/react-best-practices/SKILL.md +31 -0
  114. package/template/skills/realtime/SKILL.md +146 -0
  115. package/template/skills/review/SKILL.md +82 -0
  116. package/template/skills/testing/SKILL.md +44 -0
  117. package/template/skills/web-quality-audit/SKILL.md +47 -0
  118. 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
- # Temporary Holding Version
1
+ # Orchestra
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
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
+ ![One task, end to end](docs/img/task-lifecycle.svg#gh-light-mode-only)
60
+ ![One task, end to end](docs/img/task-lifecycle-dark.svg#gh-dark-mode-only)
61
+
62
+ ### The statuses it moves through
63
+
64
+ ![Task status lifecycle](docs/img/task-status-lifecycle.svg#gh-light-mode-only)
65
+ ![Task status lifecycle](docs/img/task-status-lifecycle-dark.svg#gh-dark-mode-only)
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");