crewly 1.11.6 → 1.12.1

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 (142) hide show
  1. package/config/skills/agent/onboarding/synthesize-hierarchy/SKILL.md +65 -0
  2. package/config/skills/agent/onboarding/synthesize-hierarchy/execute.sh +61 -0
  3. package/config/skills/agent/web-search/SKILL.md +70 -0
  4. package/config/skills/agent/web-search/execute.sh +170 -0
  5. package/config/skills/agent/web-search/skill.json +23 -0
  6. package/dist/backend/backend/src/constants.d.ts +12 -0
  7. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  8. package/dist/backend/backend/src/constants.js +12 -0
  9. package/dist/backend/backend/src/constants.js.map +1 -1
  10. package/dist/backend/backend/src/controllers/cloud/cloud.controller.d.ts +22 -0
  11. package/dist/backend/backend/src/controllers/cloud/cloud.controller.d.ts.map +1 -1
  12. package/dist/backend/backend/src/controllers/cloud/cloud.controller.js +58 -0
  13. package/dist/backend/backend/src/controllers/cloud/cloud.controller.js.map +1 -1
  14. package/dist/backend/backend/src/controllers/cloud/cloud.routes.d.ts.map +1 -1
  15. package/dist/backend/backend/src/controllers/cloud/cloud.routes.js +3 -1
  16. package/dist/backend/backend/src/controllers/cloud/cloud.routes.js.map +1 -1
  17. package/dist/backend/backend/src/controllers/orchestrator-onboarding/orchestrator-onboarding.controller.d.ts +27 -0
  18. package/dist/backend/backend/src/controllers/orchestrator-onboarding/orchestrator-onboarding.controller.d.ts.map +1 -1
  19. package/dist/backend/backend/src/controllers/orchestrator-onboarding/orchestrator-onboarding.controller.js +108 -0
  20. package/dist/backend/backend/src/controllers/orchestrator-onboarding/orchestrator-onboarding.controller.js.map +1 -1
  21. package/dist/backend/backend/src/controllers/orchestrator-onboarding/orchestrator-onboarding.routes.d.ts +6 -2
  22. package/dist/backend/backend/src/controllers/orchestrator-onboarding/orchestrator-onboarding.routes.d.ts.map +1 -1
  23. package/dist/backend/backend/src/controllers/orchestrator-onboarding/orchestrator-onboarding.routes.js +9 -3
  24. package/dist/backend/backend/src/controllers/orchestrator-onboarding/orchestrator-onboarding.routes.js.map +1 -1
  25. package/dist/backend/backend/src/index.d.ts.map +1 -1
  26. package/dist/backend/backend/src/index.js +36 -2
  27. package/dist/backend/backend/src/index.js.map +1 -1
  28. package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.d.ts +18 -0
  29. package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.d.ts.map +1 -1
  30. package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.js +24 -2
  31. package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.js.map +1 -1
  32. package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.d.ts +102 -0
  33. package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.d.ts.map +1 -0
  34. package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.js +167 -0
  35. package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.js.map +1 -0
  36. package/dist/backend/backend/src/services/fission/fission-guard.service.d.ts +21 -0
  37. package/dist/backend/backend/src/services/fission/fission-guard.service.d.ts.map +1 -1
  38. package/dist/backend/backend/src/services/fission/fission-guard.service.js +30 -0
  39. package/dist/backend/backend/src/services/fission/fission-guard.service.js.map +1 -1
  40. package/dist/backend/backend/src/services/intent-task/intent-classifier.rules.d.ts +4 -0
  41. package/dist/backend/backend/src/services/intent-task/intent-classifier.rules.d.ts.map +1 -1
  42. package/dist/backend/backend/src/services/intent-task/intent-classifier.rules.js +8 -0
  43. package/dist/backend/backend/src/services/intent-task/intent-classifier.rules.js.map +1 -1
  44. package/dist/backend/backend/src/services/orchestrator/onboarding/materialize-team.d.ts +79 -58
  45. package/dist/backend/backend/src/services/orchestrator/onboarding/materialize-team.d.ts.map +1 -1
  46. package/dist/backend/backend/src/services/orchestrator/onboarding/materialize-team.js +140 -65
  47. package/dist/backend/backend/src/services/orchestrator/onboarding/materialize-team.js.map +1 -1
  48. package/dist/backend/backend/src/services/orchestrator/onboarding/synthesize-hierarchy.d.ts +117 -0
  49. package/dist/backend/backend/src/services/orchestrator/onboarding/synthesize-hierarchy.d.ts.map +1 -0
  50. package/dist/backend/backend/src/services/orchestrator/onboarding/synthesize-hierarchy.js +189 -0
  51. package/dist/backend/backend/src/services/orchestrator/onboarding/synthesize-hierarchy.js.map +1 -0
  52. package/dist/backend/backend/src/services/orchestrator/onboarding-mode-loader.d.ts.map +1 -1
  53. package/dist/backend/backend/src/services/orchestrator/onboarding-mode-loader.js +1 -0
  54. package/dist/backend/backend/src/services/orchestrator/onboarding-mode-loader.js.map +1 -1
  55. package/dist/backend/backend/src/services/orchestrator/onboarding-mode.skill-allowlist.d.ts.map +1 -1
  56. package/dist/backend/backend/src/services/orchestrator/onboarding-mode.skill-allowlist.js +2 -0
  57. package/dist/backend/backend/src/services/orchestrator/onboarding-mode.skill-allowlist.js.map +1 -1
  58. package/dist/backend/backend/src/services/orchestrator/prompts/onboarding-mode.prompt.d.ts.map +1 -1
  59. package/dist/backend/backend/src/services/orchestrator/prompts/onboarding-mode.prompt.js +17 -1
  60. package/dist/backend/backend/src/services/orchestrator/prompts/onboarding-mode.prompt.js.map +1 -1
  61. package/dist/backend/backend/src/services/reconciler/reconcile-rules.d.ts +50 -0
  62. package/dist/backend/backend/src/services/reconciler/reconcile-rules.d.ts.map +1 -1
  63. package/dist/backend/backend/src/services/reconciler/reconcile-rules.js +71 -0
  64. package/dist/backend/backend/src/services/reconciler/reconcile-rules.js.map +1 -1
  65. package/dist/backend/backend/src/services/reconciler/reconciler.service.d.ts +18 -0
  66. package/dist/backend/backend/src/services/reconciler/reconciler.service.d.ts.map +1 -1
  67. package/dist/backend/backend/src/services/reconciler/reconciler.service.js +75 -1
  68. package/dist/backend/backend/src/services/reconciler/reconciler.service.js.map +1 -1
  69. package/dist/backend/backend/src/services/session/pty/pty-session-backend.d.ts +115 -0
  70. package/dist/backend/backend/src/services/session/pty/pty-session-backend.d.ts.map +1 -1
  71. package/dist/backend/backend/src/services/session/pty/pty-session-backend.js +189 -3
  72. package/dist/backend/backend/src/services/session/pty/pty-session-backend.js.map +1 -1
  73. package/dist/backend/backend/src/services/session/pty/pty-session.d.ts +28 -0
  74. package/dist/backend/backend/src/services/session/pty/pty-session.d.ts.map +1 -1
  75. package/dist/backend/backend/src/services/session/pty/pty-session.js +61 -1
  76. package/dist/backend/backend/src/services/session/pty/pty-session.js.map +1 -1
  77. package/dist/backend/backend/src/services/template/template.service.d.ts.map +1 -1
  78. package/dist/backend/backend/src/services/template/template.service.js +67 -2
  79. package/dist/backend/backend/src/services/template/template.service.js.map +1 -1
  80. package/dist/backend/backend/src/services/v3/cascade-request-status.d.ts +19 -1
  81. package/dist/backend/backend/src/services/v3/cascade-request-status.d.ts.map +1 -1
  82. package/dist/backend/backend/src/services/v3/cascade-request-status.js +39 -2
  83. package/dist/backend/backend/src/services/v3/cascade-request-status.js.map +1 -1
  84. package/dist/backend/backend/src/services/v3/escalation-router.service.d.ts +41 -0
  85. package/dist/backend/backend/src/services/v3/escalation-router.service.d.ts.map +1 -1
  86. package/dist/backend/backend/src/services/v3/escalation-router.service.js +169 -0
  87. package/dist/backend/backend/src/services/v3/escalation-router.service.js.map +1 -1
  88. package/dist/backend/backend/src/services/v3/request-cascade.subscriber.d.ts +4 -1
  89. package/dist/backend/backend/src/services/v3/request-cascade.subscriber.d.ts.map +1 -1
  90. package/dist/backend/backend/src/services/v3/request-cascade.subscriber.js +21 -0
  91. package/dist/backend/backend/src/services/v3/request-cascade.subscriber.js.map +1 -1
  92. package/dist/backend/backend/src/types/intent-task.types.d.ts.map +1 -1
  93. package/dist/backend/backend/src/types/intent-task.types.js +8 -0
  94. package/dist/backend/backend/src/types/intent-task.types.js.map +1 -1
  95. package/dist/backend/backend/src/types/v2/request.types.d.ts +1 -1
  96. package/dist/backend/backend/src/types/v2/request.types.d.ts.map +1 -1
  97. package/dist/backend/backend/src/types/v2/request.types.js +1 -0
  98. package/dist/backend/backend/src/types/v2/request.types.js.map +1 -1
  99. package/dist/cli/backend/src/constants.d.ts +12 -0
  100. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  101. package/dist/cli/backend/src/constants.js +12 -0
  102. package/dist/cli/backend/src/constants.js.map +1 -1
  103. package/package.json +9 -3
  104. package/packages/crewly-agent/README.md +27 -0
  105. package/packages/crewly-agent/bin/crewly-agent +33 -0
  106. package/packages/crewly-agent/package.json +39 -0
  107. package/packages/crewly-agent/src/cli.ts +168 -0
  108. package/packages/crewly-agent/src/runtime/agent-runner.service.test.ts +2355 -0
  109. package/packages/crewly-agent/src/runtime/agent-runner.service.ts +1827 -0
  110. package/packages/crewly-agent/src/runtime/agent-stream.service.test.ts +153 -0
  111. package/packages/crewly-agent/src/runtime/agent-stream.service.ts +225 -0
  112. package/packages/crewly-agent/src/runtime/agent-worker.test.ts +171 -0
  113. package/packages/crewly-agent/src/runtime/agent-worker.ts +193 -0
  114. package/packages/crewly-agent/src/runtime/api-client.ts +143 -0
  115. package/packages/crewly-agent/src/runtime/approval-queue.service.ts +307 -0
  116. package/packages/crewly-agent/src/runtime/audit-log.service.test.ts +208 -0
  117. package/packages/crewly-agent/src/runtime/audit-log.service.ts +332 -0
  118. package/packages/crewly-agent/src/runtime/audit-trail.service.test.ts +178 -0
  119. package/packages/crewly-agent/src/runtime/audit-trail.service.ts +151 -0
  120. package/packages/crewly-agent/src/runtime/auditor-tools.test.ts +274 -0
  121. package/packages/crewly-agent/src/runtime/auditor-tools.ts +311 -0
  122. package/packages/crewly-agent/src/runtime/cloud-config.ts +67 -0
  123. package/packages/crewly-agent/src/runtime/deepseek-sse-transform.test.ts +165 -0
  124. package/packages/crewly-agent/src/runtime/deepseek-sse-transform.ts +168 -0
  125. package/packages/crewly-agent/src/runtime/env-isolation.service.ts +246 -0
  126. package/packages/crewly-agent/src/runtime/in-process-log-buffer.test.ts +280 -0
  127. package/packages/crewly-agent/src/runtime/in-process-log-buffer.ts +317 -0
  128. package/packages/crewly-agent/src/runtime/index.ts +38 -0
  129. package/packages/crewly-agent/src/runtime/mcp-tool-bridge.test.ts +352 -0
  130. package/packages/crewly-agent/src/runtime/mcp-tool-bridge.ts +244 -0
  131. package/packages/crewly-agent/src/runtime/model-manager.test.ts +326 -0
  132. package/packages/crewly-agent/src/runtime/model-manager.ts +363 -0
  133. package/packages/crewly-agent/src/runtime/output-filter.service.ts +175 -0
  134. package/packages/crewly-agent/src/runtime/prompt-guard.service.ts +303 -0
  135. package/packages/crewly-agent/src/runtime/rate-limiter.test.ts +228 -0
  136. package/packages/crewly-agent/src/runtime/rate-limiter.ts +353 -0
  137. package/packages/crewly-agent/src/runtime/tool-registry.test.ts +2510 -0
  138. package/packages/crewly-agent/src/runtime/tool-registry.ts +2104 -0
  139. package/packages/crewly-agent/src/runtime/types.test.ts +519 -0
  140. package/packages/crewly-agent/src/runtime/types.ts +637 -0
  141. package/packages/crewly-agent/src/runtime/web-search.tool.test.ts +131 -0
  142. package/packages/crewly-agent/src/runtime/web-search.tool.ts +140 -0
@@ -1,108 +1,129 @@
1
1
  /**
2
- * Materialize-Team Logic (Onboarding v3, v0)
2
+ * Materialize-Team Logic (Onboarding v3)
3
3
  *
4
- * v0 stub: writes a minimal team `config.json` under `<teamsDir>/<id>/`
5
- * and flips a project `onboardingComplete` flag. Real provisioning
6
- * (template-engine wiring, agent-soul generation, system-prompt
7
- * personalisation) lands Wed–Fri — Sam's brief explicitly says a
8
- * "logs + flips flag" stub is acceptable for the Mon 5/4 EOD demo.
4
+ * Turns a confirmed {@link TeamRecommendation} into a REAL, persisted team
5
+ * that the rest of the system can run hands-off:
9
6
  *
10
- * The function is async + injection-friendly: callers pass a
11
- * `teamsDir`, a `projectFlagPath`, a UUID generator, and a clock — so
12
- * tests exercise the real write path with tmp dirs and deterministic
13
- * IDs.
7
+ * 1. Provision a live, template-backed team via the proven
8
+ * `TemplateService.createTeamFromTemplate` + `StorageService.saveTeam`
9
+ * path the same path `onboarding-provision.service.ts` uses. The
10
+ * created members carry real system prompts, skill sets, hierarchy
11
+ * (`hierarchyLevel` / `parentMemberId`) and `canDelegate` flags from the
12
+ * template, so the orchestrator can immediately delegate into the team
13
+ * and the agents auto-activate on first claim.
14
+ * 2. Flip the project `onboardingComplete` flag.
14
15
  *
15
- * Wired downstream: when this module is upgraded post-Mon, swap the
16
- * inline write for a delegation to
17
- * `backend/src/services/onboarding/onboarding-provision.service.ts`
18
- * (it already provisions teams via TemplateService see that file's
19
- * `provisionFromOnboarding`).
16
+ * Fallback: if the recommendation's `templateId` is not a registered template
17
+ * (or provisioning throws — e.g. a tier-gated template on OSS), we write the
18
+ * legacy minimal `config.json` stub so the orc never dead-ends. That stub has
19
+ * inactive members with empty prompts and is clearly marked `provisioned:false`
20
+ * so callers can warn the user that a generic team was created.
21
+ *
22
+ * History: this was a "Mon EOD v0 stub" that only wrote a dead config and
23
+ * flipped a flag (members `agentStatus:'inactive'`, empty `systemPrompt`),
24
+ * which meant every new-team goal required a human to actually stand up
25
+ * agents. P0 of the autonomy roadmap wires it to real provisioning.
26
+ *
27
+ * The function stays injection-friendly: callers pass `teamsDir`,
28
+ * `projectFlagPath`, a UUID generator, a clock, and (for tests) a
29
+ * `provisionTeam` implementation — so unit tests run against tmp dirs with
30
+ * deterministic IDs and a fake provisioner, never touching the real
31
+ * `~/.crewly` tree or the singletons.
20
32
  *
21
33
  * @module services/orchestrator/onboarding/materialize-team
22
34
  */
23
35
  import type { TeamRecommendation } from './recommend-team.js';
36
+ /** A live team produced by {@link MaterializeOptions.provisionTeam}. */
37
+ export interface ProvisionedTeam {
38
+ /** Persisted team id (from StorageService). */
39
+ readonly teamId: string;
40
+ /** Number of members created from the template. */
41
+ readonly memberCount: number;
42
+ }
24
43
  /**
25
44
  * Side-effects the materialize step needs. Injected so tests can run
26
- * against a tmp dir without touching the real `~/.crewly` tree.
45
+ * against a tmp dir + a fake provisioner without touching the real
46
+ * `~/.crewly` tree or the TemplateService/StorageService singletons.
27
47
  */
28
48
  export interface MaterializeOptions {
29
- /** Root teams directory (e.g. `~/.crewly/teams`). */
49
+ /** Root teams directory for the FALLBACK stub write (e.g. `~/.crewly/teams`). */
30
50
  readonly teamsDir: string;
31
51
  /** File path for the project onboarding-complete flag. */
32
52
  readonly projectFlagPath: string;
33
- /** UUID generator — defaults to {@link crypto.randomUUID} when omitted. */
53
+ /** UUID generator (fallback stub only) — defaults to {@link crypto.randomUUID}. */
34
54
  readonly uuid?: () => string;
35
55
  /** Clock — defaults to `() => new Date()` when omitted. */
36
56
  readonly now?: () => Date;
57
+ /** Optional logger sink — receives the materialize log lines. */
58
+ readonly log?: (message: string) => void;
59
+ /** Owner principal to attribute the created team to (multi-tenant). */
60
+ readonly ownerUserId?: string;
37
61
  /**
38
- * Optional logger sink. When provided, the function writes the
39
- * Mon-EOD-stub log lines through it (so tests can assert).
62
+ * Parent team id, set when this team is a CHILD in a nested hierarchy (P3).
63
+ * Links the created team to its parent so the parent TL coordinates it.
64
+ * Undefined for a standalone or top-level team.
40
65
  */
41
- readonly log?: (message: string) => void;
66
+ readonly parentTeamId?: string;
67
+ /**
68
+ * Team provisioner. Defaults to {@link defaultProvisionTeam}, which creates
69
+ * a live, persisted, template-backed team. Returns `null` when the
70
+ * recommendation's `templateId` is not a registered template, signalling the
71
+ * caller to fall back to a minimal stub. Tests inject a fake.
72
+ */
73
+ readonly provisionTeam?: (recommendation: TeamRecommendation, teamName: string, ownerUserId: string | undefined, parentTeamId: string | undefined) => Promise<ProvisionedTeam | null>;
42
74
  }
43
75
  /**
44
76
  * Outcome of a successful materialize call.
45
77
  */
46
78
  export interface MaterializeResult {
47
- /** Newly-generated team ID (UUID). */
79
+ /** Team ID — the persisted team id (live path) or the generated id (fallback). */
48
80
  readonly teamId: string;
49
- /** Absolute path to the team's `config.json`. */
50
- readonly teamConfigPath: string;
51
81
  /**
52
- * Always `true` for a successful call mirrors the brief's spec:
53
- * "flips `onboardingComplete = true`".
82
+ * Absolute path to the team's fallback `config.json`. Empty string on the
83
+ * live path (the team is persisted via StorageService, not a flat file).
54
84
  */
85
+ readonly teamConfigPath: string;
86
+ /** Always `true` for a successful call — mirrors "flips `onboardingComplete = true`". */
55
87
  readonly onboardingComplete: true;
56
- /** Echo of the recommendation that was materialized (for orc to summarise back to the user). */
88
+ /** Echo of the recommendation that was materialized (for the orc to summarise back). */
57
89
  readonly recommendation: TeamRecommendation;
90
+ /** Where the project flag was persisted. */
91
+ readonly projectFlagPath: string;
92
+ /** Number of members on the created team. */
93
+ readonly memberCount: number;
58
94
  /**
59
- * Where the project flag was persisted. The flag is a tiny JSON file
60
- * (`{ onboardingComplete: true, completedAt }`).
95
+ * `true` when a live, template-backed team was provisioned (real agents,
96
+ * prompts, hierarchy). `false` when provisioning was unavailable and a
97
+ * minimal stub config was written instead — the orc should tell the user a
98
+ * generic team was created and offer to refine it.
61
99
  */
62
- readonly projectFlagPath: string;
100
+ readonly provisioned: boolean;
63
101
  }
64
102
  /**
65
- * Materialize a {@link TeamRecommendation} into a team config file +
66
- * project onboarding-complete flag.
67
- *
68
- * v0 (Mon 5/4 EOD) writes a minimal config:
69
- * ```json
70
- * {
71
- * "id": "<uuid>",
72
- * "name": "<recommendation.templateId> Team",
73
- * "createdAt": "...",
74
- * "createdBy": "onboarding-v3",
75
- * "templateId": "...",
76
- * "members": [ ... ]
77
- * }
78
- * ```
79
- * No agent-soul personalisation, no project linkage, no goals.md
80
- * generation — those land Wed–Fri when this calls into
81
- * `onboarding-provision.service.ts`.
103
+ * Materialize a {@link TeamRecommendation} into a REAL team + project
104
+ * onboarding-complete flag.
82
105
  *
83
106
  * @param recommendation - Output of {@link recommendTeam} that the user confirmed.
84
- * @param opts - Side-effect injection (teamsDir, projectFlagPath, etc.).
85
- * @returns The team ID + config path + flag-path on success.
86
- * @throws If the team config write fails (filesystem error). Caller is
87
- * expected to surface a brief, honest error to the user
88
- * ("I couldn't create the team — error: …") rather than retry
89
- * silently.
107
+ * @param opts - Side-effect injection (teamsDir, projectFlagPath, provisionTeam, …).
108
+ * @returns The team ID + member count + provisioned flag + flag-path on success.
109
+ * @throws If BOTH provisioning fails AND the fallback config write fails
110
+ * (filesystem error). Caller surfaces a brief honest error rather than
111
+ * retrying silently.
90
112
  *
91
113
  * @example
92
114
  * ```ts
93
115
  * import { getCrewlyHomePath } from '../../core/crewly-home.utils.js';
94
116
  *
95
- * const crewlyHome = getCrewlyHomePath(); // honours CREWLY_HOME env override
117
+ * const crewlyHome = getCrewlyHomePath();
96
118
  * const result = await materializeTeam(rec, {
97
119
  * teamsDir: path.join(crewlyHome, 'teams'),
98
120
  * projectFlagPath: path.join(crewlyHome, 'onboarding-complete.json'),
99
121
  * });
100
- * console.log(result.teamId, '→', result.teamConfigPath);
122
+ * // result.provisioned === true → live team `result.teamId` with `result.memberCount` agents
101
123
  * ```
102
124
  *
103
- * Do NOT inline `path.join(os.homedir(), '.crewly/teams')` — that
104
- * ignores CREWLY_HOME and breaks ESTestNode + dry-run-kit isolation
105
- * (see crewly-home.utils.ts for context).
125
+ * Do NOT inline `path.join(os.homedir(), '.crewly/teams')` — that ignores
126
+ * CREWLY_HOME and breaks ESTestNode + dry-run-kit isolation.
106
127
  */
107
128
  export declare function materializeTeam(recommendation: TeamRecommendation, opts: MaterializeOptions): Promise<MaterializeResult>;
108
129
  //# sourceMappingURL=materialize-team.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"materialize-team.d.ts","sourceRoot":"","sources":["../../../../../../../backend/src/services/orchestrator/onboarding/materialize-team.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAKH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAM9D;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,qDAAqD;IACrD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,0DAA0D;IAC1D,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,2EAA2E;IAC3E,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,MAAM,CAAC;IAC7B,2DAA2D;IAC3D,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B;;;OAGG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1C;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,sCAAsC;IACtC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,iDAAiD;IACjD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC;;;OAGG;IACH,QAAQ,CAAC,kBAAkB,EAAE,IAAI,CAAC;IAClC,gGAAgG;IAChG,QAAQ,CAAC,cAAc,EAAE,kBAAkB,CAAC;IAC5C;;;OAGG;IACH,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CAClC;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,wBAAsB,eAAe,CACnC,cAAc,EAAE,kBAAkB,EAClC,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,iBAAiB,CAAC,CAqC5B"}
1
+ {"version":3,"file":"materialize-team.d.ts","sourceRoot":"","sources":["../../../../../../../backend/src/services/orchestrator/onboarding/materialize-team.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAKH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAM9D,wEAAwE;AACxE,MAAM,WAAW,eAAe;IAC9B,+CAA+C;IAC/C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,mDAAmD;IACnD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,iFAAiF;IACjF,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,0DAA0D;IAC1D,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,mFAAmF;IACnF,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,MAAM,CAAC;IAC7B,2DAA2D;IAC3D,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,iEAAiE;IACjE,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,uEAAuE;IACvE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,CACvB,cAAc,EAAE,kBAAkB,EAClC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,YAAY,EAAE,MAAM,GAAG,SAAS,KAC7B,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,kFAAkF;IAClF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,yFAAyF;IACzF,QAAQ,CAAC,kBAAkB,EAAE,IAAI,CAAC;IAClC,wFAAwF;IACxF,QAAQ,CAAC,cAAc,EAAE,kBAAkB,CAAC;IAC5C,4CAA4C;IAC5C,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,6CAA6C;IAC7C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B;;;;;OAKG;IACH,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;CAC/B;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,eAAe,CACnC,cAAc,EAAE,kBAAkB,EAClC,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,iBAAiB,CAAC,CAsE5B"}
@@ -1,22 +1,34 @@
1
1
  /**
2
- * Materialize-Team Logic (Onboarding v3, v0)
2
+ * Materialize-Team Logic (Onboarding v3)
3
3
  *
4
- * v0 stub: writes a minimal team `config.json` under `<teamsDir>/<id>/`
5
- * and flips a project `onboardingComplete` flag. Real provisioning
6
- * (template-engine wiring, agent-soul generation, system-prompt
7
- * personalisation) lands Wed–Fri — Sam's brief explicitly says a
8
- * "logs + flips flag" stub is acceptable for the Mon 5/4 EOD demo.
4
+ * Turns a confirmed {@link TeamRecommendation} into a REAL, persisted team
5
+ * that the rest of the system can run hands-off:
9
6
  *
10
- * The function is async + injection-friendly: callers pass a
11
- * `teamsDir`, a `projectFlagPath`, a UUID generator, and a clock — so
12
- * tests exercise the real write path with tmp dirs and deterministic
13
- * IDs.
7
+ * 1. Provision a live, template-backed team via the proven
8
+ * `TemplateService.createTeamFromTemplate` + `StorageService.saveTeam`
9
+ * path the same path `onboarding-provision.service.ts` uses. The
10
+ * created members carry real system prompts, skill sets, hierarchy
11
+ * (`hierarchyLevel` / `parentMemberId`) and `canDelegate` flags from the
12
+ * template, so the orchestrator can immediately delegate into the team
13
+ * and the agents auto-activate on first claim.
14
+ * 2. Flip the project `onboardingComplete` flag.
14
15
  *
15
- * Wired downstream: when this module is upgraded post-Mon, swap the
16
- * inline write for a delegation to
17
- * `backend/src/services/onboarding/onboarding-provision.service.ts`
18
- * (it already provisions teams via TemplateService see that file's
19
- * `provisionFromOnboarding`).
16
+ * Fallback: if the recommendation's `templateId` is not a registered template
17
+ * (or provisioning throws — e.g. a tier-gated template on OSS), we write the
18
+ * legacy minimal `config.json` stub so the orc never dead-ends. That stub has
19
+ * inactive members with empty prompts and is clearly marked `provisioned:false`
20
+ * so callers can warn the user that a generic team was created.
21
+ *
22
+ * History: this was a "Mon EOD v0 stub" that only wrote a dead config and
23
+ * flipped a flag (members `agentStatus:'inactive'`, empty `systemPrompt`),
24
+ * which meant every new-team goal required a human to actually stand up
25
+ * agents. P0 of the autonomy roadmap wires it to real provisioning.
26
+ *
27
+ * The function stays injection-friendly: callers pass `teamsDir`,
28
+ * `projectFlagPath`, a UUID generator, a clock, and (for tests) a
29
+ * `provisionTeam` implementation — so unit tests run against tmp dirs with
30
+ * deterministic IDs and a fake provisioner, never touching the real
31
+ * `~/.crewly` tree or the singletons.
20
32
  *
21
33
  * @module services/orchestrator/onboarding/materialize-team
22
34
  */
@@ -26,63 +38,76 @@ import * as path from 'node:path';
26
38
  // Public API
27
39
  // =============================================================================
28
40
  /**
29
- * Materialize a {@link TeamRecommendation} into a team config file +
30
- * project onboarding-complete flag.
31
- *
32
- * v0 (Mon 5/4 EOD) writes a minimal config:
33
- * ```json
34
- * {
35
- * "id": "<uuid>",
36
- * "name": "<recommendation.templateId> Team",
37
- * "createdAt": "...",
38
- * "createdBy": "onboarding-v3",
39
- * "templateId": "...",
40
- * "members": [ ... ]
41
- * }
42
- * ```
43
- * No agent-soul personalisation, no project linkage, no goals.md
44
- * generation — those land Wed–Fri when this calls into
45
- * `onboarding-provision.service.ts`.
41
+ * Materialize a {@link TeamRecommendation} into a REAL team + project
42
+ * onboarding-complete flag.
46
43
  *
47
44
  * @param recommendation - Output of {@link recommendTeam} that the user confirmed.
48
- * @param opts - Side-effect injection (teamsDir, projectFlagPath, etc.).
49
- * @returns The team ID + config path + flag-path on success.
50
- * @throws If the team config write fails (filesystem error). Caller is
51
- * expected to surface a brief, honest error to the user
52
- * ("I couldn't create the team — error: …") rather than retry
53
- * silently.
45
+ * @param opts - Side-effect injection (teamsDir, projectFlagPath, provisionTeam, …).
46
+ * @returns The team ID + member count + provisioned flag + flag-path on success.
47
+ * @throws If BOTH provisioning fails AND the fallback config write fails
48
+ * (filesystem error). Caller surfaces a brief honest error rather than
49
+ * retrying silently.
54
50
  *
55
51
  * @example
56
52
  * ```ts
57
53
  * import { getCrewlyHomePath } from '../../core/crewly-home.utils.js';
58
54
  *
59
- * const crewlyHome = getCrewlyHomePath(); // honours CREWLY_HOME env override
55
+ * const crewlyHome = getCrewlyHomePath();
60
56
  * const result = await materializeTeam(rec, {
61
57
  * teamsDir: path.join(crewlyHome, 'teams'),
62
58
  * projectFlagPath: path.join(crewlyHome, 'onboarding-complete.json'),
63
59
  * });
64
- * console.log(result.teamId, '→', result.teamConfigPath);
60
+ * // result.provisioned === true → live team `result.teamId` with `result.memberCount` agents
65
61
  * ```
66
62
  *
67
- * Do NOT inline `path.join(os.homedir(), '.crewly/teams')` — that
68
- * ignores CREWLY_HOME and breaks ESTestNode + dry-run-kit isolation
69
- * (see crewly-home.utils.ts for context).
63
+ * Do NOT inline `path.join(os.homedir(), '.crewly/teams')` — that ignores
64
+ * CREWLY_HOME and breaks ESTestNode + dry-run-kit isolation.
70
65
  */
71
66
  export async function materializeTeam(recommendation, opts) {
72
- const uuid = opts.uuid ?? defaultUuid;
73
67
  const now = opts.now ?? defaultNow;
74
68
  const log = opts.log ?? noopLog;
75
- const teamId = uuid();
76
- const teamDir = path.join(opts.teamsDir, teamId);
77
- const teamConfigPath = path.join(teamDir, 'config.json');
69
+ const provisionTeam = opts.provisionTeam ?? defaultProvisionTeam;
78
70
  const createdAt = now().toISOString();
79
- log(`[materialize-team] would materialize team for template "${recommendation.templateId}" with ${recommendation.agents.length} agents (id=${teamId})`);
80
- // 1. Write the team config.
81
- const config = buildTeamConfig(recommendation, teamId, createdAt);
82
- await fs.mkdir(teamDir, { recursive: true });
83
- await fs.writeFile(teamConfigPath, JSON.stringify(config, null, 2) + '\n', 'utf8');
71
+ const teamName = humanizeTemplateName(recommendation.templateId);
72
+ log(`[materialize-team] materializing template "${recommendation.templateId}" (${recommendation.agents.length} recommended agents)`);
73
+ // 1. Provision a live, persisted, template-backed team when possible.
74
+ let teamId;
75
+ let memberCount;
76
+ let teamConfigPath = '';
77
+ let provisioned;
78
+ let live = null;
79
+ try {
80
+ live = await provisionTeam(recommendation, teamName, opts.ownerUserId, opts.parentTeamId);
81
+ }
82
+ catch (err) {
83
+ // Tier-gated template, missing registry, or storage error — don't dead-end
84
+ // the orc; drop to the minimal fallback with a warning.
85
+ log(`[materialize-team] WARN live provisioning failed for template "${recommendation.templateId}" ` +
86
+ `(${err instanceof Error ? err.message : String(err)}) — falling back to a minimal team`);
87
+ }
88
+ if (live) {
89
+ teamId = live.teamId;
90
+ memberCount = live.memberCount;
91
+ provisioned = true;
92
+ log(`[materialize-team] provisioned LIVE team id=${teamId} (${memberCount} members) from template "${recommendation.templateId}"`);
93
+ }
94
+ else {
95
+ // Fallback: template not registered / provisioning unavailable. Write a
96
+ // minimal stub config so the orc still has a team to talk about.
97
+ const uuid = opts.uuid ?? defaultUuid;
98
+ teamId = uuid();
99
+ const teamDir = path.join(opts.teamsDir, teamId);
100
+ teamConfigPath = path.join(teamDir, 'config.json');
101
+ const config = buildTeamConfig(recommendation, teamId, createdAt);
102
+ memberCount = recommendation.agents.length;
103
+ provisioned = false;
104
+ await fs.mkdir(teamDir, { recursive: true });
105
+ await fs.writeFile(teamConfigPath, JSON.stringify(config, null, 2) + '\n', 'utf8');
106
+ log(`[materialize-team] wrote MINIMAL fallback config id=${teamId} ` +
107
+ `(template "${recommendation.templateId}" not provisionable)`);
108
+ }
84
109
  // 2. Flip the project onboarding-complete flag.
85
- const flag = { onboardingComplete: true, completedAt: createdAt };
110
+ const flag = { onboardingComplete: true, completedAt: createdAt, teamId };
86
111
  await fs.mkdir(path.dirname(opts.projectFlagPath), { recursive: true });
87
112
  await fs.writeFile(opts.projectFlagPath, JSON.stringify(flag, null, 2) + '\n', 'utf8');
88
113
  log(`[materialize-team] flipped onboardingComplete = true at ${opts.projectFlagPath}`);
@@ -92,14 +117,54 @@ export async function materializeTeam(recommendation, opts) {
92
117
  onboardingComplete: true,
93
118
  recommendation,
94
119
  projectFlagPath: opts.projectFlagPath,
120
+ memberCount,
121
+ provisioned,
95
122
  };
96
123
  }
97
124
  // =============================================================================
98
125
  // Internals
99
126
  // =============================================================================
100
127
  /**
101
- * Build the minimal v0 team config. Members are derived 1:1 from the
102
- * recommendation's agents list.
128
+ * Default team provisioner: create a live, persisted team from the
129
+ * recommendation's template via the same path `onboarding-provision.service.ts`
130
+ * uses. Lazy-imports the singletons so this module stays dependency-light and
131
+ * unit-testable (callers inject a fake `provisionTeam` instead).
132
+ *
133
+ * @param recommendation - The confirmed recommendation (carries `templateId`).
134
+ * @param teamName - Human-readable team name to assign.
135
+ * @param ownerUserId - Owner principal, or undefined for OSS single-user mode.
136
+ * @returns The persisted team id + member count, or `null` when the template
137
+ * is not registered (caller falls back to a minimal stub).
138
+ * @throws Propagates a tier-gating error from `createTeamFromTemplate` (the
139
+ * caller catches it and falls back).
140
+ */
141
+ async function defaultProvisionTeam(recommendation, teamName, ownerUserId, parentTeamId) {
142
+ const { TemplateService } = await import('../../template/template.service.js');
143
+ const { StorageService } = await import('../../core/storage.service.js');
144
+ const result = TemplateService.getInstance().createTeamFromTemplate(recommendation.templateId, teamName);
145
+ if (!result)
146
+ return null;
147
+ // Attribute to the authenticated principal (multi-tenant). Undefined in OSS
148
+ // single-user mode leaves the team unscoped (legacy behaviour).
149
+ if (ownerUserId !== undefined) {
150
+ result.team.ownerUserId = ownerUserId;
151
+ }
152
+ // Link to the parent team when this is a child in a nested hierarchy (P3).
153
+ if (parentTeamId !== undefined) {
154
+ result.team.parentTeamId = parentTeamId;
155
+ }
156
+ await StorageService.getInstance().saveTeam(result.team);
157
+ return { teamId: result.team.id, memberCount: result.memberCount };
158
+ }
159
+ /**
160
+ * Build the minimal FALLBACK team config. Members are derived 1:1 from the
161
+ * recommendation's agents list, inactive with empty prompts. Only used when
162
+ * live provisioning is unavailable.
163
+ *
164
+ * @param rec - The recommendation to materialize.
165
+ * @param teamId - The generated team id.
166
+ * @param createdAt - ISO creation timestamp.
167
+ * @returns A plain config object ready to JSON-serialize.
103
168
  */
104
169
  function buildTeamConfig(rec, teamId, createdAt) {
105
170
  return {
@@ -124,10 +189,10 @@ function buildTeamConfig(rec, teamId, createdAt) {
124
189
  }
125
190
  /**
126
191
  * Convert a kebab-case template id → human team name
127
- * (`"dtc-viral-content-team"` → `"Dtc Viral Content Team"`). The full
128
- * personalisation pass happens post-Mon when we wire into
129
- * `onboarding-provision.service.ts` that service already builds
130
- * proper names.
192
+ * (`"dtc-viral-content-team"` → `"Dtc Viral Content Team"`).
193
+ *
194
+ * @param templateId - The kebab-case template id.
195
+ * @returns A title-cased, space-separated name.
131
196
  */
132
197
  function humanizeTemplateName(templateId) {
133
198
  return templateId
@@ -137,6 +202,9 @@ function humanizeTemplateName(templateId) {
137
202
  }
138
203
  /**
139
204
  * Convert a kebab-case role → human display name.
205
+ *
206
+ * @param role - The kebab-case role id.
207
+ * @returns A title-cased, space-separated name.
140
208
  */
141
209
  function humanizeRoleName(role) {
142
210
  return role
@@ -145,20 +213,27 @@ function humanizeRoleName(role) {
145
213
  .join(' ');
146
214
  }
147
215
  /**
148
- * Default UUID generator. Uses Node's `crypto.randomUUID` so we don't
149
- * pull in a dep, and so the output is deterministic-shaped.
216
+ * Default UUID generator (fallback stub only).
217
+ *
218
+ * @returns A random UUID string.
150
219
  */
151
220
  function defaultUuid() {
152
- // Lazy require to keep the import surface minimal and avoid loading
153
- // `node:crypto` at module load.
154
221
  const { randomUUID } = require('node:crypto');
155
222
  return randomUUID();
156
223
  }
157
- /** Default clock — wall-clock time. */
224
+ /**
225
+ * Default clock — wall-clock time.
226
+ *
227
+ * @returns The current Date.
228
+ */
158
229
  function defaultNow() {
159
230
  return new Date();
160
231
  }
161
- /** Default log sink — drops the message on the floor. */
232
+ /**
233
+ * Default log sink — drops the message on the floor.
234
+ *
235
+ * @param _message - Ignored.
236
+ */
162
237
  function noopLog(_message) {
163
238
  /* intentional no-op */
164
239
  }
@@ -1 +1 @@
1
- {"version":3,"file":"materialize-team.js","sourceRoot":"","sources":["../../../../../../../backend/src/services/orchestrator/onboarding/materialize-team.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"materialize-team.js","sourceRoot":"","sources":["../../../../../../../backend/src/services/orchestrator/onboarding/materialize-team.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Nested sub-team synthesis (Autonomy roadmap P3).
3
+ *
4
+ * When a goal needs PARALLEL work-streams (e.g. "build a SaaS with a frontend,
5
+ * a backend, and DevOps"), a single flat team is the wrong shape — you want a
6
+ * top coordination team whose lead (TL) delegates to per-stream CHILD teams,
7
+ * each with its own TL who decomposes + verifies its slice and reports up.
8
+ * The data model already supports this (`Team.parentTeamId`,
9
+ * `TeamMember.parentMemberId`/`hierarchyLevel`) but nothing DECIDED the shape
10
+ * or instantiated it — complex goals had to be wired by hand.
11
+ *
12
+ * This module adds that decision + instantiation:
13
+ * 1. {@link detectStreams} — heuristically find the parallel streams in a goal.
14
+ * 2. {@link synthesizeHierarchyPlan} — turn them into a parent + child-team
15
+ * plan (or a single flat team when <2 streams), capped by a branching
16
+ * limit aligned with fission-guard's `maxBranchingFactor`.
17
+ * 3. {@link materializeHierarchy} — instantiate the parent then each child via
18
+ * the P0 {@link materializeTeam} path, linking children to the parent.
19
+ *
20
+ * The stream detection is heuristic (v1) — same spirit as the hardcoded
21
+ * `recommendTeam` mappings; a semantic/LLM planner is a later upgrade. The
22
+ * STRUCTURE (parent + linked children, real provisioning) is the deliverable.
23
+ *
24
+ * @module services/orchestrator/onboarding/synthesize-hierarchy
25
+ */
26
+ import { type BusinessContext, type TeamRecommendation } from './recommend-team.js';
27
+ import { type MaterializeOptions } from './materialize-team.js';
28
+ /**
29
+ * Default cap on child teams in a single hierarchy. Aligned with fission-guard's
30
+ * `maxBranchingFactor` so the synthesized shape never exceeds the runtime's
31
+ * fan-out guardrail.
32
+ */
33
+ export declare const DEFAULT_MAX_SUBTEAMS = 5;
34
+ /**
35
+ * Detect the parallel work-streams named in a goal context.
36
+ *
37
+ * @param ctx - The business context (goal/industry + tasks).
38
+ * @returns Stream keys (e.g. `['frontend','backend','infra']`) in canonical order.
39
+ */
40
+ export declare function detectStreams(ctx: BusinessContext): string[];
41
+ /** One child team in a synthesized hierarchy. */
42
+ export interface HierarchyNode {
43
+ /** The stream this child team owns (e.g. `frontend`). */
44
+ readonly stream: string;
45
+ /** The team recommendation for this child. */
46
+ readonly recommendation: TeamRecommendation;
47
+ }
48
+ /** A synthesized team hierarchy: a parent coordination team + child teams. */
49
+ export interface HierarchyPlan {
50
+ /** Top coordination team (its TL delegates to + accepts from the children). */
51
+ readonly parent: TeamRecommendation;
52
+ /** Per-stream child teams. Empty → a single flat team is sufficient. */
53
+ readonly children: readonly HierarchyNode[];
54
+ /** Human-readable rationale for the shape. */
55
+ readonly rationale: string;
56
+ }
57
+ /** Options for {@link synthesizeHierarchyPlan}. */
58
+ export interface SynthesizeOptions {
59
+ /** Max child teams (default {@link DEFAULT_MAX_SUBTEAMS}). */
60
+ readonly maxSubteams?: number;
61
+ }
62
+ /**
63
+ * Synthesize a (possibly nested) team plan for a goal.
64
+ *
65
+ * If fewer than 2 parallel streams are detected, returns a single flat team
66
+ * (no children) — nesting would be overhead. Otherwise returns a parent
67
+ * coordination team plus one child team per detected stream, capped at
68
+ * `maxSubteams`.
69
+ *
70
+ * @param ctx - The goal/business context.
71
+ * @param opts - Synthesis options (branching cap).
72
+ * @returns The hierarchy plan.
73
+ *
74
+ * @example
75
+ * ```ts
76
+ * const plan = synthesizeHierarchyPlan({
77
+ * industry: 'build a SaaS with a React frontend, a Node API backend, and DevOps',
78
+ * scale: 'small-team',
79
+ * tasks: [],
80
+ * });
81
+ * // plan.children → frontend / backend / infra child teams under a parent
82
+ * ```
83
+ */
84
+ export declare function synthesizeHierarchyPlan(ctx: BusinessContext, opts?: SynthesizeOptions): HierarchyPlan;
85
+ /** A child team that was instantiated as part of a hierarchy. */
86
+ export interface MaterializedChild {
87
+ readonly stream: string;
88
+ readonly teamId: string;
89
+ readonly memberCount: number;
90
+ readonly parentTeamId: string;
91
+ readonly provisioned: boolean;
92
+ }
93
+ /** Result of {@link materializeHierarchy}. */
94
+ export interface MaterializedHierarchy {
95
+ readonly parentTeamId: string;
96
+ readonly parentMemberCount: number;
97
+ readonly parentProvisioned: boolean;
98
+ readonly children: readonly MaterializedChild[];
99
+ }
100
+ /**
101
+ * Instantiate a {@link HierarchyPlan}: materialize the parent team, then each
102
+ * child team linked to the parent via `parentTeamId`. Reuses the P0
103
+ * {@link materializeTeam} path (real, persisted, template-backed teams).
104
+ *
105
+ * The same `opts` (teamsDir, projectFlagPath, ownerUserId, provisionTeam, …)
106
+ * is used for every team; the per-child `parentTeamId` is injected by this
107
+ * function. When the plan has no children, only the parent is created (this is
108
+ * equivalent to a single {@link materializeTeam} call).
109
+ *
110
+ * @param plan - The hierarchy plan from {@link synthesizeHierarchyPlan}.
111
+ * @param opts - Materialize options shared across all teams.
112
+ * @returns The created parent + children team ids with parent links.
113
+ * @throws If the PARENT materialize fails (a child failure is surfaced via its
114
+ * `provisioned` flag, not thrown — partial hierarchies are usable).
115
+ */
116
+ export declare function materializeHierarchy(plan: HierarchyPlan, opts: MaterializeOptions): Promise<MaterializedHierarchy>;
117
+ //# sourceMappingURL=synthesize-hierarchy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"synthesize-hierarchy.d.ts","sourceRoot":"","sources":["../../../../../../../backend/src/services/orchestrator/onboarding/synthesize-hierarchy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACxB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,uBAAuB,CAAC;AAM/B;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,IAAI,CAAC;AA8BtC;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,EAAE,CAK5D;AAqBD,iDAAiD;AACjD,MAAM,WAAW,aAAa;IAC5B,yDAAyD;IACzD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,8CAA8C;IAC9C,QAAQ,CAAC,cAAc,EAAE,kBAAkB,CAAC;CAC7C;AAED,8EAA8E;AAC9E,MAAM,WAAW,aAAa;IAC5B,+EAA+E;IAC/E,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;IACpC,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,CAAC;IAC5C,8CAA8C;IAC9C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,mDAAmD;AACnD,MAAM,WAAW,iBAAiB;IAChC,8DAA8D;IAC9D,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAeD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,eAAe,EACpB,IAAI,GAAE,iBAAsB,GAC3B,aAAa,CA2Bf;AAMD,iEAAiE;AACjE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;CAC/B;AAED,8CAA8C;AAC9C,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,SAAS,iBAAiB,EAAE,CAAC;CACjD;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,aAAa,EACnB,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,qBAAqB,CAAC,CA0BhC"}