agentic-team 0.0.0-stage → 6.2.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 (121) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +189 -2
  3. package/bin/build-template.js +208 -0
  4. package/bin/index.js +1334 -0
  5. package/bin/platforms.js +510 -0
  6. package/package.json +41 -4
  7. package/template/.claude-plugin/plugin.json +10 -0
  8. package/template/.orchestra/README.md +391 -0
  9. package/template/.orchestra/blueprints/README.md +87 -0
  10. package/template/.orchestra/blueprints/api-only.md +46 -0
  11. package/template/.orchestra/blueprints/component-crud-resource.md +25 -0
  12. package/template/.orchestra/blueprints/saas-starter.md +69 -0
  13. package/template/.orchestra/config.yml +293 -0
  14. package/template/.orchestra/roles/orchestrator.md +105 -0
  15. package/template/.orchestra/roles/product-manager.md +439 -0
  16. package/template/.orchestra/scripts/compact-diff.awk +45 -0
  17. package/template/.orchestra/scripts/context.mjs +373 -0
  18. package/template/.orchestra/stacks/README.md +81 -0
  19. package/template/.orchestra/stacks/_lib/common.sh +3095 -0
  20. package/template/.orchestra/stacks/_repo/setup.sh +1113 -0
  21. package/template/.orchestra/stacks/backend-hono/claude/commands/endpoint.md +13 -0
  22. package/template/.orchestra/stacks/backend-hono/claude/skills/api-endpoint/SKILL.md +111 -0
  23. package/template/.orchestra/stacks/backend-hono/claude/skills/testing/SKILL.md +75 -0
  24. package/template/.orchestra/stacks/backend-hono/setup.sh +5945 -0
  25. package/template/.orchestra/stacks/backend-hono/stack.md +195 -0
  26. package/template/.orchestra/stacks/mobile-android-native/claude/commands/component.md +13 -0
  27. package/template/.orchestra/stacks/mobile-android-native/claude/skills/design-component/SKILL.md +58 -0
  28. package/template/.orchestra/stacks/mobile-android-native/setup.sh +607 -0
  29. package/template/.orchestra/stacks/mobile-android-native/stack.md +138 -0
  30. package/template/.orchestra/stacks/mobile-expo/claude/commands/component.md +12 -0
  31. package/template/.orchestra/stacks/mobile-expo/claude/skills/design-component/SKILL.md +92 -0
  32. package/template/.orchestra/stacks/mobile-expo/setup.sh +470 -0
  33. package/template/.orchestra/stacks/mobile-expo/stack.md +141 -0
  34. package/template/.orchestra/stacks/mobile-ios-native/claude/commands/component.md +12 -0
  35. package/template/.orchestra/stacks/mobile-ios-native/claude/skills/design-component/SKILL.md +58 -0
  36. package/template/.orchestra/stacks/mobile-ios-native/setup.sh +468 -0
  37. package/template/.orchestra/stacks/mobile-ios-native/stack.md +130 -0
  38. package/template/.orchestra/stacks/web-nextjs/claude/commands/component.md +12 -0
  39. package/template/.orchestra/stacks/web-nextjs/claude/skills/design-component/SKILL.md +100 -0
  40. package/template/.orchestra/stacks/web-nextjs/claude/skills/design-tokens/SKILL.md +61 -0
  41. package/template/.orchestra/stacks/web-nextjs/setup.sh +128 -0
  42. package/template/.orchestra/stacks/web-nextjs/stack.md +170 -0
  43. package/template/.orchestra/stacks/web-vite-react/claude/commands/component.md +12 -0
  44. package/template/.orchestra/stacks/web-vite-react/claude/skills/design-component/SKILL.md +100 -0
  45. package/template/.orchestra/stacks/web-vite-react/claude/skills/design-tokens/SKILL.md +61 -0
  46. package/template/.orchestra/stacks/web-vite-react/setup.sh +185 -0
  47. package/template/.orchestra/stacks/web-vite-react/stack.md +177 -0
  48. package/template/.orchestra/trackers/github.sh +467 -0
  49. package/template/CLAUDE.md +54 -0
  50. package/template/agents/architect.md +83 -0
  51. package/template/agents/engineer-high.md +17 -0
  52. package/template/agents/engineer-low.md +17 -0
  53. package/template/agents/engineer-max.md +17 -0
  54. package/template/agents/engineer-medium.md +17 -0
  55. package/template/agents/engineer-xhigh.md +17 -0
  56. package/template/agents/lead.md +925 -0
  57. package/template/agents/milestone-reviewer.md +65 -0
  58. package/template/agents/orchestrator.md +105 -0
  59. package/template/agents/product-manager.md +439 -0
  60. package/template/agents/re-reviewer.md +25 -0
  61. package/template/agents/reviewer.md +303 -0
  62. package/template/agents/scaffolder.md +206 -0
  63. package/template/agents/tracker.md +202 -0
  64. package/template/commands/blueprint.md +23 -0
  65. package/template/commands/create-role.md +64 -0
  66. package/template/commands/export.md +45 -0
  67. package/template/commands/help.md +56 -0
  68. package/template/commands/hotfix.md +14 -0
  69. package/template/commands/orchestrator.md +12 -0
  70. package/template/commands/pm.md +18 -0
  71. package/template/commands/rewind.md +63 -0
  72. package/template/commands/setup.md +15 -0
  73. package/template/commands/start.md +29 -0
  74. package/template/commands/status.md +11 -0
  75. package/template/commands/sync.md +76 -0
  76. package/template/commands/verifier.md +53 -0
  77. package/template/hooks/audit-context.sh +166 -0
  78. package/template/hooks/enforce-role.sh +193 -0
  79. package/template/hooks/protect-system-files.sh +123 -0
  80. package/template/hooks/review-rounds.sh +172 -0
  81. package/template/rules/acceptance-check.orchestra.md +11 -0
  82. package/template/rules/analytics-kpi.orchestra.md +56 -0
  83. package/template/rules/code-standards.orchestra.md +35 -0
  84. package/template/rules/comments.orchestra.md +77 -0
  85. package/template/rules/commit-format.orchestra.md +20 -0
  86. package/template/rules/dependency-upgrade.orchestra.md +112 -0
  87. package/template/rules/design-parity.orchestra.md +181 -0
  88. package/template/rules/observability.orchestra.md +121 -0
  89. package/template/rules/performance.orchestra.md +190 -0
  90. package/template/rules/phase-limits.orchestra.md +3 -0
  91. package/template/rules/pull-request.orchestra.md +218 -0
  92. package/template/rules/role-boundaries.orchestra.md +132 -0
  93. package/template/rules/security.orchestra.md +106 -0
  94. package/template/rules/stuck-detection.orchestra.md +25 -0
  95. package/template/rules/testing-standards.orchestra.md +219 -0
  96. package/template/rules/tracker-authority.orchestra.md +198 -0
  97. package/template/rules/verification-gate.orchestra.md +56 -0
  98. package/template/skills/accessibility/SKILL.md +31 -0
  99. package/template/skills/android-testing/SKILL.md +112 -0
  100. package/template/skills/architecture/SKILL.md +175 -0
  101. package/template/skills/auth-setup/SKILL.md +105 -0
  102. package/template/skills/best-practices/SKILL.md +29 -0
  103. package/template/skills/code-optimizer/SKILL.md +27 -0
  104. package/template/skills/core-web-vitals/SKILL.md +32 -0
  105. package/template/skills/crud-api/SKILL.md +32 -0
  106. package/template/skills/debug/SKILL.md +28 -0
  107. package/template/skills/deployment/SKILL.md +104 -0
  108. package/template/skills/error-handling/SKILL.md +154 -0
  109. package/template/skills/frontend-design/SKILL.md +30 -0
  110. package/template/skills/fullstack-infrastructure/SKILL.md +108 -0
  111. package/template/skills/ios-testing/SKILL.md +100 -0
  112. package/template/skills/mobile-testing/SKILL.md +102 -0
  113. package/template/skills/observability/SKILL.md +91 -0
  114. package/template/skills/project-structure/SKILL.md +114 -0
  115. package/template/skills/push-notifications/SKILL.md +146 -0
  116. package/template/skills/react-best-practices/SKILL.md +31 -0
  117. package/template/skills/realtime/SKILL.md +146 -0
  118. package/template/skills/review/SKILL.md +82 -0
  119. package/template/skills/testing/SKILL.md +45 -0
  120. package/template/skills/web-quality-audit/SKILL.md +47 -0
  121. 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,190 @@
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
+ Only the project's platforms are installed — `web`, `expo`, `ios`, `android`,
28
+ `backend` — from `project.platforms` in `config.yml`, detected from the repo
29
+ when it is empty, or `--platforms ios,backend`. See
30
+ [Getting started](docs/getting-started.md#only-your-platforms).
31
+
32
+ ## How it works
33
+
34
+ Once, in a freshly cloned empty repo:
35
+
36
+ ```
37
+ /orchestra:setup
38
+ ```
39
+
40
+ It asks what you are building and scaffolds each app from a stack — every
41
+ version resolved from the registry, CI, Dependabot, the PR template, the
42
+ commit hook and the verification gate already in place. Nothing is written
43
+ from memory.
44
+
45
+ Then, for every feature, two terminals:
46
+
47
+ ```
48
+ Terminal 1 — PM Terminal 2 — Lead
49
+ /orchestra:pm /orchestra:start
50
+ talk the idea through reads the board
51
+ milestones → phases → review design → RFC
52
+ "export" → the board one task → one PR
53
+ /orchestra:sync on your comments reviewer on the PR
54
+ /orchestra:sync on your comments
55
+ ```
56
+
57
+ The PM writes the plan and gets it reviewed. When you say "export", every
58
+ approved milestone goes to the board in one burst — an epic per milestone, a
59
+ task per phase, all in `backlog`. You move a task to `ready`; lead takes it
60
+ from there and nowhere else.
61
+
62
+ ### One task, end to end
63
+
64
+ ![One task, end to end](docs/img/task-lifecycle.svg#gh-light-mode-only)
65
+ ![One task, end to end](docs/img/task-lifecycle-dark.svg#gh-dark-mode-only)
66
+
67
+ ### The statuses it moves through
68
+
69
+ ![Task status lifecycle](docs/img/task-status-lifecycle.svg#gh-light-mode-only)
70
+ ![Task status lifecycle](docs/img/task-status-lifecycle-dark.svg#gh-dark-mode-only)
71
+
72
+ Two moves are yours: `backlog → ready` and `blocked → ready`. Lead sets the
73
+ rest, and never moves a task to `ready` itself. A re-export updates a task's
74
+ text and never its status.
75
+
76
+ A comment on a task is how you change things. About the plan — scope,
77
+ acceptance criteria, a phase to split — the PM answers it: revises the
78
+ phase, re-exports, replies. About the build — a bug, a design mismatch —
79
+ lead answers it with a pull request. Each surfaces the other's kind and
80
+ stops. Never edit a requirement by hand on the board; the next export
81
+ overwrites it.
82
+
83
+ With `tracker.provider: none` there is no board. The markdown under
84
+ `.orchestra/milestones/` is the source of truth and lead reads it from disk.
85
+
86
+ ## Commands
87
+
88
+ | Command | Who | What |
89
+ |---|---|---|
90
+ | `/orchestra:setup` | you, once | Scaffold the repo from stacks |
91
+ | `/orchestra:pm` | you | Open the PM terminal |
92
+ | `/orchestra:start` | you | Open the lead terminal; `--auto` runs unattended and merges its own PRs |
93
+ | `/orchestra:export [id]` | PM, when you ask | Push approved milestones to the board |
94
+ | `/orchestra:sync [id]` | PM or lead | Act on what changed on the board |
95
+ | `/orchestra:status` | PM | Milestone status report |
96
+ | `/orchestra:verifier [N]` | PM | Check built milestones against their requirements |
97
+ | `/orchestra:rewind [N]` | PM | Execution history: decisions, metrics, retries |
98
+ | `/orchestra:hotfix {desc}` | you | Implement → verify → commit → push, fast |
99
+ | `/orchestra:blueprint {name}` | PM | Milestones from a template; `add` saves one |
100
+ | `/orchestra:orchestrator` | you | Maintain the system itself |
101
+ | `/orchestra:create-role` | Orchestrator | A new role, interactively |
102
+ | `/orchestra:help` | anyone | All of the above |
103
+
104
+ ## What is inside
105
+
106
+ ```
107
+ .orchestra/
108
+ ├── config.yml pipeline, verification, testing, delivery, tracker, observability
109
+ ├── roles/ product-manager, orchestrator — identity and what each may write
110
+ ├── stacks/ how each kind of app is scaffolded and built afterwards
111
+ ├── trackers/ the GitHub adapter; ClickUp goes through its MCP connector
112
+ ├── blueprints/ milestone templates
113
+ └── milestones/ your work — prd, milestone, phases, tracker.yml, context/decisions/journal
114
+
115
+ .claude/
116
+ ├── agents/ architect, scaffolder, lead, reviewer, re-reviewer, tracker
117
+ ├── rules/*.orchestra.md discipline, loaded into every session
118
+ ├── skills/*/SKILL.md depth on one topic, loaded per phase
119
+ └── commands/orchestra/ the commands above
120
+ ```
121
+
122
+ **Stacks:** `web-nextjs`, `web-vite-react`, `backend-hono`, `mobile-expo`,
123
+ `mobile-ios-native`, `mobile-android-native`. A defect found while building a
124
+ real project is fixed in the stack, so the next project never meets it.
125
+
126
+ **Rules** are the discipline that applies everywhere: verification gate,
127
+ testing shape, security, performance, observability, commit format, pull
128
+ requests, tracker authority, comments. What a rule can decide mechanically
129
+ is enforced by `scripts/policy-check.mjs` in the gate; the rest is a review
130
+ item, and the reviewer is told which is which.
131
+
132
+ **Roles** write only inside their ownership. PM writes milestones. Lead
133
+ writes the milestone record — `context.md`, `decisions.md`, `journal.md`. Sub-agents write what a phase's scope names. A
134
+ `PreToolUse` hook blocks everything else.
135
+
136
+ ## Principles
137
+
138
+ Each one exists because ignoring it produced a real failure.
139
+
140
+ - **Verified, never recalled.** Versions come from the registry, flags from
141
+ `--help`, OWASP settings from the page — at run time.
142
+ - **Determinism over improvisation.** Scaffolding is a script. It runs the
143
+ same way every time and lands in a diff.
144
+ - **Enforcement over advice.** A rule nothing checks is prose. Conventions
145
+ are backed by CI, hooks, coverage gates and a policy script.
146
+ - **A green suite is the merge signal.** Everything wrapping a third-party
147
+ library has a test, so a dependency bump that changes behaviour turns red.
148
+ - **One source of truth.** `tracker.provider` names it. Never both.
149
+ - **Measure before building.** A milestone states its metric, baseline,
150
+ target and how it is read — or it is not ready.
151
+ - **Report honestly.** Say what was verified and what was assumed. Unverified
152
+ is a word.
153
+
154
+ ## Upgrading
155
+
156
+ ```bash
157
+ npx agentic-team@latest
158
+ ```
159
+
160
+ | What | On upgrade |
161
+ |---|---|
162
+ | Roles, rules, agents, commands, stacks, shipped skills | Updated |
163
+ | Your own roles, skills, rules | Preserved |
164
+ | Blueprints (shipped / yours) | Updated / preserved |
165
+ | `milestones/` | Untouched |
166
+ | `config.yml` | Merged — your values kept, new keys added |
167
+
168
+ ## Documentation
169
+
170
+ - [Getting started](docs/getting-started.md)
171
+ - [Commands](docs/commands.md)
172
+ - [Roles](docs/roles.md)
173
+ - [Features](docs/features.md)
174
+ - [Stacks](docs/stacks.md)
175
+ - [Skills](docs/skills.md)
176
+ - [Blueprints](docs/blueprints.md)
177
+
178
+ ## Development
179
+
180
+ ```bash
181
+ yarn test
182
+ ```
183
+
184
+ `bin/index.js` is the installer. `template/` is built from `.orchestra/` and
185
+ `.claude/` by `yarn template`, is gitignored, and is regenerated on every
186
+ publish. Pre-commit runs the template build and the suite.
187
+
188
+ ## License
189
+
190
+ 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/agentic-team",
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 agentic-team 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");