crewly 1.20.162 → 1.20.164
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config/roles/orchestrator/prompt.md +2 -0
- package/config/roles/team-leader/prompt.md +2 -0
- package/config/roles/team-leader/tl-addon.md +2 -0
- package/config/skills/agent/core/project-tickets/SKILL.md +4 -0
- package/config/skills/orchestrator/set-team-lead/SKILL.md +58 -0
- package/config/skills/orchestrator/set-team-lead/execute.sh +46 -0
- package/config/skills/orchestrator/set-team-lead/execute.test.sh +77 -0
- package/dist/backend/backend/src/constants.d.ts +31 -1
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +39 -2
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/project-tickets/project-tickets.controller.d.ts +1 -1
- package/dist/backend/backend/src/controllers/project-tickets/project-tickets.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/project-tickets/project-tickets.controller.js +6 -1
- package/dist/backend/backend/src/controllers/project-tickets/project-tickets.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/team/team.controller.d.ts +15 -0
- package/dist/backend/backend/src/controllers/team/team.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/team/team.controller.js +110 -15
- package/dist/backend/backend/src/controllers/team/team.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/team/team.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/team/team.routes.js +3 -1
- package/dist/backend/backend/src/controllers/team/team.routes.js.map +1 -1
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +9 -15
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/models/Team.d.ts.map +1 -1
- package/dist/backend/backend/src/models/Team.js +5 -9
- package/dist/backend/backend/src/models/Team.js.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.js +20 -28
- package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/idle-detection.service.d.ts +26 -0
- package/dist/backend/backend/src/services/agent/idle-detection.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/idle-detection.service.js +43 -0
- package/dist/backend/backend/src/services/agent/idle-detection.service.js.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-builder.service.d.ts +18 -6
- package/dist/backend/backend/src/services/ai/prompt-builder.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-builder.service.js +21 -23
- package/dist/backend/backend/src/services/ai/prompt-builder.service.js.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/huddle-leader.d.ts +23 -0
- package/dist/backend/backend/src/services/chat-v2/huddle-leader.d.ts.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/huddle-leader.js +37 -0
- package/dist/backend/backend/src/services/chat-v2/huddle-leader.js.map +1 -0
- package/dist/backend/backend/src/services/core/storage.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/core/storage.service.js +3 -0
- package/dist/backend/backend/src/services/core/storage.service.js.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/project-ticket-workflow.service.d.ts +28 -7
- package/dist/backend/backend/src/services/project-tickets/project-ticket-workflow.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/project-ticket-workflow.service.js +51 -14
- package/dist/backend/backend/src/services/project-tickets/project-ticket-workflow.service.js.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/ticket-assignee-waker.d.ts +70 -0
- package/dist/backend/backend/src/services/project-tickets/ticket-assignee-waker.d.ts.map +1 -0
- package/dist/backend/backend/src/services/project-tickets/ticket-assignee-waker.js +64 -0
- package/dist/backend/backend/src/services/project-tickets/ticket-assignee-waker.js.map +1 -0
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-decision.d.ts +24 -0
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-decision.d.ts.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-decision.js +38 -1
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-decision.js.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-messages.d.ts +14 -2
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-messages.d.ts.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-messages.js +33 -3
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-messages.js.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.d.ts +13 -2
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.js +43 -12
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-instance-registry.service.js +2 -2
- package/dist/backend/backend/src/services/slack/slack-instance-registry.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts +10 -1
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.js +19 -8
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
- package/dist/backend/backend/src/services/team-health/live-team-health-data-provider.d.ts.map +1 -1
- package/dist/backend/backend/src/services/team-health/live-team-health-data-provider.js +4 -3
- package/dist/backend/backend/src/services/team-health/live-team-health-data-provider.js.map +1 -1
- package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.boot.d.ts +4 -3
- package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.boot.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.boot.js +6 -7
- package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.boot.js.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-owner.resolver.d.ts.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-owner.resolver.js +2 -1
- package/dist/backend/backend/src/services/wiki/wiki-owner.resolver.js.map +1 -1
- package/dist/backend/backend/src/types/index.d.ts +3 -2
- package/dist/backend/backend/src/types/index.d.ts.map +1 -1
- package/dist/backend/backend/src/types/index.js.map +1 -1
- package/dist/backend/backend/src/utils/defaultPrompts.d.ts.map +1 -1
- package/dist/backend/backend/src/utils/defaultPrompts.js +8 -0
- package/dist/backend/backend/src/utils/defaultPrompts.js.map +1 -1
- package/dist/backend/backend/src/utils/member-default-model.utils.d.ts +5 -5
- package/dist/backend/backend/src/utils/member-default-model.utils.d.ts.map +1 -1
- package/dist/backend/backend/src/utils/member-default-model.utils.js +4 -4
- package/dist/backend/backend/src/utils/member-default-model.utils.js.map +1 -1
- package/dist/backend/backend/src/utils/team.utils.d.ts +129 -18
- package/dist/backend/backend/src/utils/team.utils.d.ts.map +1 -1
- package/dist/backend/backend/src/utils/team.utils.js +240 -28
- package/dist/backend/backend/src/utils/team.utils.js.map +1 -1
- package/dist/backend/build-info.json +2 -2
- package/dist/cli/backend/src/constants.d.ts +31 -1
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +39 -2
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/models/Team.d.ts.map +1 -1
- package/dist/cli/backend/src/models/Team.js +5 -9
- package/dist/cli/backend/src/models/Team.js.map +1 -1
- package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/agent-registration.service.js +20 -28
- package/dist/cli/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/cli/backend/src/services/ai/prompt-builder.service.d.ts +18 -6
- package/dist/cli/backend/src/services/ai/prompt-builder.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/ai/prompt-builder.service.js +21 -23
- package/dist/cli/backend/src/services/ai/prompt-builder.service.js.map +1 -1
- package/dist/cli/backend/src/services/core/storage.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/core/storage.service.js +3 -0
- package/dist/cli/backend/src/services/core/storage.service.js.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts +10 -1
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.js +19 -8
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
- package/dist/cli/backend/src/types/index.d.ts +3 -2
- package/dist/cli/backend/src/types/index.d.ts.map +1 -1
- package/dist/cli/backend/src/types/index.js.map +1 -1
- package/dist/cli/backend/src/utils/member-default-model.utils.d.ts +5 -5
- package/dist/cli/backend/src/utils/member-default-model.utils.d.ts.map +1 -1
- package/dist/cli/backend/src/utils/member-default-model.utils.js +4 -4
- package/dist/cli/backend/src/utils/member-default-model.utils.js.map +1 -1
- package/dist/cli/backend/src/utils/team.utils.d.ts +129 -18
- package/dist/cli/backend/src/utils/team.utils.d.ts.map +1 -1
- package/dist/cli/backend/src/utils/team.utils.js +240 -28
- package/dist/cli/backend/src/utils/team.utils.js.map +1 -1
- package/frontend/dist/assets/{index-64c8a616.js → index-9153caca.js} +263 -263
- package/frontend/dist/index.html +1 -1
- package/package.json +1 -1
|
@@ -28,6 +28,13 @@ Communication style:
|
|
|
28
28
|
- Provide constructive feedback when reviewing outputs
|
|
29
29
|
- Escalate to Orchestrator when issues cannot be resolved locally
|
|
30
30
|
- Report progress and results concisely`,
|
|
31
|
+
'tech-lead': `You are an AI Tech Lead: you lead your team technically and hands-on.
|
|
32
|
+
|
|
33
|
+
Your responsibilities:
|
|
34
|
+
- Make the technical decisions and review your team's work
|
|
35
|
+
- Delegate each task to the member whose role fits it; take only lead-level work yourself
|
|
36
|
+
- Keep the owner informed and unblock the team
|
|
37
|
+
- Write code yourself only when no member fits the work`,
|
|
31
38
|
tpm: `You are an AI Technical Product Manager (TPM) responsible for scoping projects and translating business logic into technical requirements.
|
|
32
39
|
|
|
33
40
|
Your responsibilities:
|
|
@@ -280,6 +287,7 @@ export function getDefaultTeamMemberName(role, index = 0) {
|
|
|
280
287
|
const roleNames = {
|
|
281
288
|
orchestrator: 'Orchestrator',
|
|
282
289
|
'team-leader': 'Team Leader',
|
|
290
|
+
'tech-lead': 'Tech Lead',
|
|
283
291
|
tpm: 'Technical Product Manager',
|
|
284
292
|
architect: 'Architect',
|
|
285
293
|
pgm: 'Program Manager',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaultPrompts.js","sourceRoot":"","sources":["../../../../../backend/src/utils/defaultPrompts.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,sBAAsB,GAAmC;IACpE,YAAY,EAAE;;;;;;;;;;;;;oDAaoC;IAElD,aAAa,EAAE;;;;;;;;;;;;;;wCAcuB;IAEtC,GAAG,EAAE;;;;;;;;;;;;;;;;;;;;;;6DAsBsD;IAE3D,GAAG,EAAE;;;;;;;;;;;;;;;;;;;;;;2DAsBoD;IAEzD,SAAS,EAAE;;;;;;;;;;;;;2CAa8B;IAEzC,oBAAoB,EAAE;;;;;;;;;;;;;;;;;;;2DAmBmC;IAEzD,mBAAmB,EAAE;;;;;;;;;;;;;;;;;;;yDAmBkC;IAEvD,EAAE,EAAE;;;;;;;;;;;;;0CAaoC;IAExC,MAAM,EAAE;;;;;;;;;;;;;8CAaoC;IAE5C,QAAQ,EAAE;;;;;;;;;;;;;6CAaiC;IAE3C,SAAS,EAAE;;;;;;;;;;;;;;;;;;;8DAmBiD;IAE5D,eAAe,EAAE;;;;;;;;;;;;;;;;;;;wDAmBqC;IAEtD,aAAa,EAAE;;;;;;;;;;;;;;;;;;;6CAmB4B;IAE3C,iBAAiB,EAAE;;;;;;;;;;;;;0CAaqB;IAExC,KAAK,EAAE;;;;;;;;;;;;;wDAa+C;IAEtD,OAAO,EAAE;;;;;;;;;;;;;uDAa4C;CACtD,CAAC;AAEF,MAAM,UAAU,gBAAgB,CAAC,IAAoB;IACnD,OAAO,sBAAsB,CAAC,IAAI,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,IAAoB,EAAE,QAAgB,CAAC;IAC9E,MAAM,SAAS,GAAmC;QAChD,YAAY,EAAE,cAAc;QAC5B,aAAa,EAAE,aAAa;QAC5B,GAAG,EAAE,2BAA2B;QAChC,SAAS,EAAE,WAAW;QACtB,GAAG,EAAE,iBAAiB;QACtB,SAAS,EAAE,WAAW;QACtB,oBAAoB,EAAE,oBAAoB;QAC1C,mBAAmB,EAAE,mBAAmB;QACxC,eAAe,EAAE,sBAAsB;QACvC,EAAE,EAAE,aAAa;QACjB,aAAa,EAAE,aAAa;QAC5B,MAAM,EAAE,eAAe;QACvB,QAAQ,EAAE,UAAU;QACpB,iBAAiB,EAAE,iBAAiB;QACpC,KAAK,EAAE,sBAAsB;QAC7B,OAAO,EAAE,kBAAkB;KAC5B,CAAC;IAEF,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IACjC,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,QAAQ,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;AAC7D,CAAC"}
|
|
1
|
+
{"version":3,"file":"defaultPrompts.js","sourceRoot":"","sources":["../../../../../backend/src/utils/defaultPrompts.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,sBAAsB,GAAmC;IACpE,YAAY,EAAE;;;;;;;;;;;;;oDAaoC;IAElD,aAAa,EAAE;;;;;;;;;;;;;;wCAcuB;IAEtC,WAAW,EAAE;;;;;;wDAMyC;IAEtD,GAAG,EAAE;;;;;;;;;;;;;;;;;;;;;;6DAsBsD;IAE3D,GAAG,EAAE;;;;;;;;;;;;;;;;;;;;;;2DAsBoD;IAEzD,SAAS,EAAE;;;;;;;;;;;;;2CAa8B;IAEzC,oBAAoB,EAAE;;;;;;;;;;;;;;;;;;;2DAmBmC;IAEzD,mBAAmB,EAAE;;;;;;;;;;;;;;;;;;;yDAmBkC;IAEvD,EAAE,EAAE;;;;;;;;;;;;;0CAaoC;IAExC,MAAM,EAAE;;;;;;;;;;;;;8CAaoC;IAE5C,QAAQ,EAAE;;;;;;;;;;;;;6CAaiC;IAE3C,SAAS,EAAE;;;;;;;;;;;;;;;;;;;8DAmBiD;IAE5D,eAAe,EAAE;;;;;;;;;;;;;;;;;;;wDAmBqC;IAEtD,aAAa,EAAE;;;;;;;;;;;;;;;;;;;6CAmB4B;IAE3C,iBAAiB,EAAE;;;;;;;;;;;;;0CAaqB;IAExC,KAAK,EAAE;;;;;;;;;;;;;wDAa+C;IAEtD,OAAO,EAAE;;;;;;;;;;;;;uDAa4C;CACtD,CAAC;AAEF,MAAM,UAAU,gBAAgB,CAAC,IAAoB;IACnD,OAAO,sBAAsB,CAAC,IAAI,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,IAAoB,EAAE,QAAgB,CAAC;IAC9E,MAAM,SAAS,GAAmC;QAChD,YAAY,EAAE,cAAc;QAC5B,aAAa,EAAE,aAAa;QAC5B,WAAW,EAAE,WAAW;QACxB,GAAG,EAAE,2BAA2B;QAChC,SAAS,EAAE,WAAW;QACtB,GAAG,EAAE,iBAAiB;QACtB,SAAS,EAAE,WAAW;QACtB,oBAAoB,EAAE,oBAAoB;QAC1C,mBAAmB,EAAE,mBAAmB;QACxC,eAAe,EAAE,sBAAsB;QACvC,EAAE,EAAE,aAAa;QACjB,aAAa,EAAE,aAAa;QAC5B,MAAM,EAAE,eAAe;QACvB,QAAQ,EAAE,UAAU;QACpB,iBAAiB,EAAE,iBAAiB;QACpC,KAAK,EAAE,sBAAsB;QAC7B,OAAO,EAAE,kBAAkB;KAC5B,CAAC;IAEF,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IACjC,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,QAAQ,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;AAC7D,CAAC"}
|
|
@@ -27,14 +27,14 @@ export declare function reviewedMemberDefaultModel(env?: NodeJS.ProcessEnv): str
|
|
|
27
27
|
/**
|
|
28
28
|
* Whether someone other than the member reviews its work: a parent member
|
|
29
29
|
* that exists in the team, or a team lead who is not the member itself.
|
|
30
|
-
* Members that lead (
|
|
31
|
-
* with no parent) never count as reviewed.
|
|
30
|
+
* Members that lead (a lead by the team-lead rule in `utils/team.utils`, or a
|
|
31
|
+
* delegating member with no parent) never count as reviewed.
|
|
32
32
|
*
|
|
33
33
|
* @param team - The member's team
|
|
34
34
|
* @param member - The member
|
|
35
35
|
* @returns True when the member has a reviewer above it
|
|
36
36
|
*/
|
|
37
|
-
export declare function memberHasReviewer(team: Pick<Team, 'id' | 'name' | 'members'>, member: MemberLike): boolean;
|
|
37
|
+
export declare function memberHasReviewer(team: Pick<Team, 'id' | 'name' | 'members' | 'leaderIds' | 'leaderId'>, member: MemberLike): boolean;
|
|
38
38
|
/**
|
|
39
39
|
* The model a member should launch with when it has no `modelId` of its
|
|
40
40
|
* own. Returns null when no default applies (explicit model set, not Claude
|
|
@@ -51,7 +51,7 @@ export declare function memberHasReviewer(team: Pick<Team, 'id' | 'name' | 'memb
|
|
|
51
51
|
* defaultModelForMember(team, lead); // null → Claude Code's own default (Opus)
|
|
52
52
|
* ```
|
|
53
53
|
*/
|
|
54
|
-
export declare function defaultModelForMember(team: Pick<Team, 'id' | 'name' | 'members'>, member: MemberLike, env?: NodeJS.ProcessEnv): string | null;
|
|
54
|
+
export declare function defaultModelForMember(team: Pick<Team, 'id' | 'name' | 'members' | 'leaderIds' | 'leaderId'>, member: MemberLike, env?: NodeJS.ProcessEnv): string | null;
|
|
55
55
|
/**
|
|
56
56
|
* The model id a member launches with: its own `modelId` when set, else the
|
|
57
57
|
* reviewed-member default from {@link defaultModelForMember}.
|
|
@@ -61,6 +61,6 @@ export declare function defaultModelForMember(team: Pick<Team, 'id' | 'name' | '
|
|
|
61
61
|
* @param env - Environment (tests)
|
|
62
62
|
* @returns Model id to pass to the runtime, or undefined for the runtime's own default
|
|
63
63
|
*/
|
|
64
|
-
export declare function effectiveMemberModelId(team: Pick<Team, 'id' | 'name' | 'members'>, member: MemberLike, env?: NodeJS.ProcessEnv): string | undefined;
|
|
64
|
+
export declare function effectiveMemberModelId(team: Pick<Team, 'id' | 'name' | 'members' | 'leaderIds' | 'leaderId'>, member: MemberLike, env?: NodeJS.ProcessEnv): string | undefined;
|
|
65
65
|
export {};
|
|
66
66
|
//# sourceMappingURL=member-default-model.utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"member-default-model.utils.d.ts","sourceRoot":"","sources":["../../../../../backend/src/utils/member-default-model.utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAG1D,kDAAkD;AAClD,KAAK,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,gBAAgB,CAAC,GAAG;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GACzH,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC,CAAC;AAE3C;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,GAAG,IAAI,CAM9F;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,CAAC,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,
|
|
1
|
+
{"version":3,"file":"member-default-model.utils.d.ts","sourceRoot":"","sources":["../../../../../backend/src/utils/member-default-model.utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAG1D,kDAAkD;AAClD,KAAK,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,gBAAgB,CAAC,GAAG;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GACzH,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC,CAAC;AAE3C;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,GAAG,IAAI,CAM9F;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,CAAC,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAQrI;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,CAAC,EACtE,MAAM,EAAE,UAAU,EAClB,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,GAAG,IAAI,CAMf;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,CAAC,EACtE,MAAM,EAAE,UAAU,EAClB,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,GAAG,SAAS,CAGpB"}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* @module utils/member-default-model
|
|
14
14
|
*/
|
|
15
15
|
import { MEMBER_MODEL_DEFAULT_CONSTANTS, ORCHESTRATOR_SESSION_NAME, RUNTIME_TYPES } from '../constants.js';
|
|
16
|
-
import { pickTeamLead } from './team.utils.js';
|
|
16
|
+
import { isTeamLead, pickTeamLead } from './team.utils.js';
|
|
17
17
|
/**
|
|
18
18
|
* The model reviewed members get when they have none, after the env override.
|
|
19
19
|
*
|
|
@@ -32,15 +32,15 @@ export function reviewedMemberDefaultModel(env = process.env) {
|
|
|
32
32
|
/**
|
|
33
33
|
* Whether someone other than the member reviews its work: a parent member
|
|
34
34
|
* that exists in the team, or a team lead who is not the member itself.
|
|
35
|
-
* Members that lead (
|
|
36
|
-
* with no parent) never count as reviewed.
|
|
35
|
+
* Members that lead (a lead by the team-lead rule in `utils/team.utils`, or a
|
|
36
|
+
* delegating member with no parent) never count as reviewed.
|
|
37
37
|
*
|
|
38
38
|
* @param team - The member's team
|
|
39
39
|
* @param member - The member
|
|
40
40
|
* @returns True when the member has a reviewer above it
|
|
41
41
|
*/
|
|
42
42
|
export function memberHasReviewer(team, member) {
|
|
43
|
-
if (
|
|
43
|
+
if (isTeamLead(team, member))
|
|
44
44
|
return false;
|
|
45
45
|
const members = team.members ?? [];
|
|
46
46
|
const parent = member.parentMemberId ? members.find((m) => m.id === member.parentMemberId) : undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"member-default-model.utils.js","sourceRoot":"","sources":["../../../../../backend/src/utils/member-default-model.utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,8BAA8B,EAAE,yBAAyB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAE3G,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"member-default-model.utils.js","sourceRoot":"","sources":["../../../../../backend/src/utils/member-default-model.utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,8BAA8B,EAAE,yBAAyB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAE3G,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAM3D;;;;;GAKG;AACH,MAAM,UAAU,0BAA0B,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC7E,MAAM,GAAG,GAAG,GAAG,CAAC,8BAA8B,CAAC,YAAY,CAAC,CAAC;IAC7D,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,8BAA8B,CAAC,6BAA6B,CAAC;IAC3F,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IACzB,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,WAAW,EAAE,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC;IACzD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAsE,EAAE,MAAkB;IAC1H,IAAI,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;IACnC,MAAM,MAAM,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACvG,IAAI,MAAM,IAAI,MAAM,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC;IACnD,IAAI,MAAM,CAAC,WAAW,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,cAAc;QAAE,OAAO,KAAK,CAAC;IACxE,MAAM,IAAI,GAAG,YAAY,CAAC,IAAY,CAAC,CAAC;IACxC,OAAO,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,CAAC;AACzC,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,qBAAqB,CACnC,IAAsE,EACtE,MAAkB,EAClB,MAAyB,OAAO,CAAC,GAAG;IAEpC,IAAI,MAAM,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAChC,IAAI,CAAC,MAAM,CAAC,WAAW,IAAI,aAAa,CAAC,WAAW,CAAC,KAAK,aAAa,CAAC,WAAW;QAAE,OAAO,IAAI,CAAC;IACjG,IAAI,MAAM,CAAC,IAAI,KAAK,cAAc,IAAI,MAAM,CAAC,WAAW,KAAK,yBAAyB;QAAE,OAAO,IAAI,CAAC;IACpG,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IAClD,OAAO,0BAA0B,CAAC,GAAG,CAAC,CAAC;AACzC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,sBAAsB,CACpC,IAAsE,EACtE,MAAkB,EAClB,MAAyB,OAAO,CAAC,GAAG;IAEpC,IAAI,MAAM,CAAC,OAAO;QAAE,OAAO,MAAM,CAAC,OAAO,CAAC;IAC1C,OAAO,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,IAAI,SAAS,CAAC;AAC/D,CAAC"}
|
|
@@ -2,33 +2,105 @@
|
|
|
2
2
|
* Team utility helpers
|
|
3
3
|
*
|
|
4
4
|
* Shared, dependency-free helpers operating on the `Team` / `TeamMember`
|
|
5
|
-
* shape.
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* shape. Every module that needs to know who leads a team asks here — the
|
|
6
|
+
* one rule (specs/2026-09-30-team-lead-rule.md):
|
|
7
|
+
*
|
|
8
|
+
* 1. the team's explicit `leaderIds` (or the deprecated `leaderId`), when
|
|
9
|
+
* at least one of them is still a member;
|
|
10
|
+
* 2. otherwise every member whose role is in
|
|
11
|
+
* {@link TEAM_LEAD_CONSTANTS.LEAD_ROLES} (`team-leader`, `tech-lead`).
|
|
12
|
+
*
|
|
13
|
+
* `canDelegate` is NOT part of the rule. It stays a separate "delegation
|
|
14
|
+
* authority" flag for the hierarchy (sub-leads with subordinates) and is the
|
|
15
|
+
* last-resort routing fallback of {@link pickTeamLead}. A rule lead always
|
|
16
|
+
* counts as able to delegate (see {@link canMemberDelegate}).
|
|
8
17
|
*
|
|
9
18
|
* @module utils/team.utils
|
|
10
19
|
*/
|
|
20
|
+
import { TEAM_LEAD_CONSTANTS } from '../constants.js';
|
|
11
21
|
import type { Team, TeamMember } from '../types/index.js';
|
|
22
|
+
/** The team fields the lead rule reads. */
|
|
23
|
+
export type TeamLeadSource = {
|
|
24
|
+
members?: Array<Pick<TeamMember, 'id' | 'role'>>;
|
|
25
|
+
leaderIds?: string[];
|
|
26
|
+
leaderId?: string;
|
|
27
|
+
};
|
|
28
|
+
/** How {@link setTeamLead} changes the leads. */
|
|
29
|
+
export type SetTeamLeadMode = (typeof TEAM_LEAD_CONSTANTS.SET_LEAD_MODES)[number];
|
|
30
|
+
/**
|
|
31
|
+
* Whether a role is a lead role (used only when the team names no lead).
|
|
32
|
+
*
|
|
33
|
+
* @param role - Member role
|
|
34
|
+
* @returns True for `team-leader` / `tech-lead`
|
|
35
|
+
*/
|
|
36
|
+
export declare function isLeadRole(role: string | undefined | null): boolean;
|
|
12
37
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
*
|
|
38
|
+
* The ids of the members who lead a team — THE lead rule.
|
|
39
|
+
*
|
|
40
|
+
* @param team - Team
|
|
41
|
+
* @returns Lead member ids (explicit ones, else lead-role members); empty when the team has no lead
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```typescript
|
|
45
|
+
* getTeamLeadIds({ members: [{ id: 'o', role: 'tech-lead' }, { id: 'n', role: 'developer' }] }); // ['o']
|
|
46
|
+
* getTeamLeadIds({ leaderIds: ['n'], members: [...] }); // ['n']
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export declare function getTeamLeadIds(team: TeamLeadSource): string[];
|
|
50
|
+
/**
|
|
51
|
+
* Whether a member leads its team (see {@link getTeamLeadIds}).
|
|
52
|
+
*
|
|
53
|
+
* @param team - The member's team
|
|
54
|
+
* @param member - The member
|
|
55
|
+
* @returns True for a team lead
|
|
56
|
+
*/
|
|
57
|
+
export declare function isTeamLead(team: TeamLeadSource, member: Pick<TeamMember, 'id'>): boolean;
|
|
58
|
+
/**
|
|
59
|
+
* The lead members of a team, in rule order.
|
|
60
|
+
*
|
|
61
|
+
* @param team - Team
|
|
62
|
+
* @returns Lead members (may be empty)
|
|
63
|
+
*/
|
|
64
|
+
export declare function getTeamLeads(team: Team): TeamMember[];
|
|
65
|
+
/**
|
|
66
|
+
* Whether a member may delegate: a team lead by the rule, or a member the
|
|
67
|
+
* hierarchy flagged with `canDelegate` (a sub-lead of its subordinates).
|
|
68
|
+
* This is what lead-only prompt modules (TL addon, TL soul overlay, TL
|
|
69
|
+
* skills) and delegation checks key on, so a lead set by the rule gets them
|
|
70
|
+
* on its next wake without a separate flag.
|
|
71
|
+
*
|
|
72
|
+
* @param team - The member's team
|
|
73
|
+
* @param member - The member
|
|
74
|
+
* @returns True when the member may delegate
|
|
75
|
+
*/
|
|
76
|
+
export declare function canMemberDelegate(team: TeamLeadSource, member: Pick<TeamMember, 'id' | 'canDelegate'>): boolean;
|
|
77
|
+
/**
|
|
78
|
+
* The members a delegating member directs: its `subordinateIds` (or the
|
|
79
|
+
* members naming it as parent); for a rule lead with neither, every other
|
|
80
|
+
* member that is not itself a lead and reports to nobody else.
|
|
81
|
+
*
|
|
82
|
+
* @param team - The member's team
|
|
83
|
+
* @param member - The member
|
|
84
|
+
* @returns Subordinate members (may be empty)
|
|
85
|
+
*/
|
|
86
|
+
export declare function getLeadSubordinates(team: Team, member: TeamMember): TeamMember[];
|
|
87
|
+
/**
|
|
88
|
+
* Choose the ONE member to route "the team lead" traffic to.
|
|
89
|
+
*
|
|
90
|
+
* Resolution (first match wins):
|
|
91
|
+
* 1. A lead by the rule ({@link getTeamLeadIds}); among several, the one
|
|
92
|
+
* the hierarchy marks as top (`hierarchyLevel === 1 && canDelegate`),
|
|
93
|
+
* else the first.
|
|
94
|
+
* 2. Legacy routing fallback — a member flagged `canDelegate` (hierarchy
|
|
95
|
+
* data imported without `leaderIds` or a lead role). Not a lead by the
|
|
96
|
+
* rule; kept so escalations of such teams still reach someone.
|
|
97
|
+
* 3. First member — better to dispatch to _someone_ than silently drop a
|
|
98
|
+
* `@team` ping. **Emits a warn-log (#332)**.
|
|
27
99
|
*
|
|
28
100
|
* Returns `null` only when the team has no members at all.
|
|
29
101
|
*
|
|
30
102
|
* @param team - The matched team.
|
|
31
|
-
* @returns The
|
|
103
|
+
* @returns The member to dispatch to, or `null` when the team has no members.
|
|
32
104
|
*
|
|
33
105
|
* @example
|
|
34
106
|
* ```typescript
|
|
@@ -37,4 +109,43 @@ import type { Team, TeamMember } from '../types/index.js';
|
|
|
37
109
|
* ```
|
|
38
110
|
*/
|
|
39
111
|
export declare function pickTeamLead(team: Team): TeamMember | null;
|
|
112
|
+
/**
|
|
113
|
+
* Store the lead rule's answer on the team (idempotent migration, run on
|
|
114
|
+
* every load and save): a team with no usable explicit leads but with
|
|
115
|
+
* lead-role members gets `leaderIds` = those members; `leaderId` always
|
|
116
|
+
* mirrors `leaderIds[0]` for back-compat. The rule's answer never changes —
|
|
117
|
+
* only where it is stored. Dangling explicit ids (members since removed)
|
|
118
|
+
* are dropped when at least one explicit lead remains.
|
|
119
|
+
*
|
|
120
|
+
* @param team - Team (mutated)
|
|
121
|
+
* @returns True when the team changed
|
|
122
|
+
*/
|
|
123
|
+
export declare function normalizeTeamLeaderIds(team: {
|
|
124
|
+
members?: Array<Pick<TeamMember, 'id' | 'role'>>;
|
|
125
|
+
leaderIds?: string[];
|
|
126
|
+
leaderId?: string;
|
|
127
|
+
}): boolean;
|
|
128
|
+
/**
|
|
129
|
+
* Make a member a lead of its team (`POST /api/teams/:id/lead`, the
|
|
130
|
+
* `set-team-lead` skill, the dashboard "Make lead" toggle).
|
|
131
|
+
*
|
|
132
|
+
* - `set` (default): the member becomes THE lead. Former leads lose the
|
|
133
|
+
* lead's delegation flag, and members that reported to a former lead now
|
|
134
|
+
* report to the new one.
|
|
135
|
+
* - `add`: the member joins the existing leads.
|
|
136
|
+
*
|
|
137
|
+
* The lead gets `canDelegate = true` (so the in-process delegation guard and
|
|
138
|
+
* hierarchy views agree) and `hierarchyLevel = 1` on hierarchical teams.
|
|
139
|
+
*
|
|
140
|
+
* @param team - Team (mutated)
|
|
141
|
+
* @param memberId - Member to make lead
|
|
142
|
+
* @param mode - `set` or `add`
|
|
143
|
+
* @returns The lead ids before and after
|
|
144
|
+
* @throws Error when the member is not on the team or is the orchestrator
|
|
145
|
+
*/
|
|
146
|
+
export declare function setTeamLead(team: Team, memberId: string, mode?: SetTeamLeadMode): {
|
|
147
|
+
before: string[];
|
|
148
|
+
after: string[];
|
|
149
|
+
changed: boolean;
|
|
150
|
+
};
|
|
40
151
|
//# sourceMappingURL=team.utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"team.utils.d.ts","sourceRoot":"","sources":["../../../../../backend/src/utils/team.utils.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"team.utils.d.ts","sourceRoot":"","sources":["../../../../../backend/src/utils/team.utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAkB1D,2CAA2C;AAC3C,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC;IACjD,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,iDAAiD;AACjD,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,mBAAmB,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAElF;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,CAEnE;AAeD;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,EAAE,CAI7D;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,GAAG,OAAO,CAExF;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,UAAU,EAAE,CAIrD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,aAAa,CAAC,GAAG,OAAO,CAE/G;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,GAAG,UAAU,EAAE,CAkBhF;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,UAAU,GAAG,IAAI,CAwB1D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE;IAAE,OAAO,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAqBnJ;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,GAAE,eAAuB,GAAG;IAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAkChJ"}
|
|
@@ -2,34 +2,156 @@
|
|
|
2
2
|
* Team utility helpers
|
|
3
3
|
*
|
|
4
4
|
* Shared, dependency-free helpers operating on the `Team` / `TeamMember`
|
|
5
|
-
* shape.
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* shape. Every module that needs to know who leads a team asks here — the
|
|
6
|
+
* one rule (specs/2026-09-30-team-lead-rule.md):
|
|
7
|
+
*
|
|
8
|
+
* 1. the team's explicit `leaderIds` (or the deprecated `leaderId`), when
|
|
9
|
+
* at least one of them is still a member;
|
|
10
|
+
* 2. otherwise every member whose role is in
|
|
11
|
+
* {@link TEAM_LEAD_CONSTANTS.LEAD_ROLES} (`team-leader`, `tech-lead`).
|
|
12
|
+
*
|
|
13
|
+
* `canDelegate` is NOT part of the rule. It stays a separate "delegation
|
|
14
|
+
* authority" flag for the hierarchy (sub-leads with subordinates) and is the
|
|
15
|
+
* last-resort routing fallback of {@link pickTeamLead}. A rule lead always
|
|
16
|
+
* counts as able to delegate (see {@link canMemberDelegate}).
|
|
8
17
|
*
|
|
9
18
|
* @module utils/team.utils
|
|
10
19
|
*/
|
|
20
|
+
import { TEAM_LEAD_CONSTANTS } from '../constants.js';
|
|
11
21
|
import { LoggerService } from '../services/core/logger.service.js';
|
|
12
|
-
const logger = LoggerService.getInstance().createComponentLogger('TeamUtils');
|
|
13
22
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
* The component logger, created on first use: this module is imported by
|
|
24
|
+
* storage and the Team model, and suites that mock LoggerService must be
|
|
25
|
+
* able to load it without a working logger.
|
|
26
|
+
*
|
|
27
|
+
* @returns The logger, or null when none is available
|
|
28
|
+
*/
|
|
29
|
+
function teamLogger() {
|
|
30
|
+
try {
|
|
31
|
+
return LoggerService.getInstance()?.createComponentLogger('TeamUtils') ?? null;
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Whether a role is a lead role (used only when the team names no lead).
|
|
39
|
+
*
|
|
40
|
+
* @param role - Member role
|
|
41
|
+
* @returns True for `team-leader` / `tech-lead`
|
|
42
|
+
*/
|
|
43
|
+
export function isLeadRole(role) {
|
|
44
|
+
return TEAM_LEAD_CONSTANTS.LEAD_ROLES.includes(String(role ?? ''));
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The explicit lead ids a team stores (`leaderIds`, else the legacy
|
|
48
|
+
* `leaderId`), limited to ids that are still members.
|
|
49
|
+
*
|
|
50
|
+
* @param team - Team
|
|
51
|
+
* @returns Explicit lead ids, in stored order (may be empty)
|
|
52
|
+
*/
|
|
53
|
+
function explicitLeadIds(team) {
|
|
54
|
+
const memberIds = new Set((team.members ?? []).map((m) => m.id));
|
|
55
|
+
const stored = team.leaderIds && team.leaderIds.length > 0 ? team.leaderIds : team.leaderId ? [team.leaderId] : [];
|
|
56
|
+
return [...new Set(stored)].filter((id) => memberIds.has(id));
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The ids of the members who lead a team — THE lead rule.
|
|
60
|
+
*
|
|
61
|
+
* @param team - Team
|
|
62
|
+
* @returns Lead member ids (explicit ones, else lead-role members); empty when the team has no lead
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```typescript
|
|
66
|
+
* getTeamLeadIds({ members: [{ id: 'o', role: 'tech-lead' }, { id: 'n', role: 'developer' }] }); // ['o']
|
|
67
|
+
* getTeamLeadIds({ leaderIds: ['n'], members: [...] }); // ['n']
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export function getTeamLeadIds(team) {
|
|
71
|
+
const explicit = explicitLeadIds(team);
|
|
72
|
+
if (explicit.length > 0)
|
|
73
|
+
return explicit;
|
|
74
|
+
return (team.members ?? []).filter((m) => isLeadRole(m.role)).map((m) => m.id);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Whether a member leads its team (see {@link getTeamLeadIds}).
|
|
78
|
+
*
|
|
79
|
+
* @param team - The member's team
|
|
80
|
+
* @param member - The member
|
|
81
|
+
* @returns True for a team lead
|
|
82
|
+
*/
|
|
83
|
+
export function isTeamLead(team, member) {
|
|
84
|
+
return getTeamLeadIds(team).includes(member.id);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The lead members of a team, in rule order.
|
|
88
|
+
*
|
|
89
|
+
* @param team - Team
|
|
90
|
+
* @returns Lead members (may be empty)
|
|
91
|
+
*/
|
|
92
|
+
export function getTeamLeads(team) {
|
|
93
|
+
const ids = getTeamLeadIds(team);
|
|
94
|
+
const members = team.members ?? [];
|
|
95
|
+
return ids.map((id) => members.find((m) => m.id === id)).filter((m) => !!m);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Whether a member may delegate: a team lead by the rule, or a member the
|
|
99
|
+
* hierarchy flagged with `canDelegate` (a sub-lead of its subordinates).
|
|
100
|
+
* This is what lead-only prompt modules (TL addon, TL soul overlay, TL
|
|
101
|
+
* skills) and delegation checks key on, so a lead set by the rule gets them
|
|
102
|
+
* on its next wake without a separate flag.
|
|
103
|
+
*
|
|
104
|
+
* @param team - The member's team
|
|
105
|
+
* @param member - The member
|
|
106
|
+
* @returns True when the member may delegate
|
|
107
|
+
*/
|
|
108
|
+
export function canMemberDelegate(team, member) {
|
|
109
|
+
return member.canDelegate === true || isTeamLead(team, member);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* The members a delegating member directs: its `subordinateIds` (or the
|
|
113
|
+
* members naming it as parent); for a rule lead with neither, every other
|
|
114
|
+
* member that is not itself a lead and reports to nobody else.
|
|
115
|
+
*
|
|
116
|
+
* @param team - The member's team
|
|
117
|
+
* @param member - The member
|
|
118
|
+
* @returns Subordinate members (may be empty)
|
|
119
|
+
*/
|
|
120
|
+
export function getLeadSubordinates(team, member) {
|
|
121
|
+
const members = team.members ?? [];
|
|
122
|
+
const explicit = new Set([
|
|
123
|
+
...(member.subordinateIds ?? []),
|
|
124
|
+
...members.filter((m) => m.parentMemberId === member.id).map((m) => m.id),
|
|
125
|
+
]);
|
|
126
|
+
explicit.delete(member.id);
|
|
127
|
+
if (explicit.size > 0)
|
|
128
|
+
return members.filter((m) => explicit.has(m.id));
|
|
129
|
+
if (!isTeamLead(team, member))
|
|
130
|
+
return [];
|
|
131
|
+
const leadIds = new Set(getTeamLeadIds(team));
|
|
132
|
+
const memberIds = new Set(members.map((m) => m.id));
|
|
133
|
+
return members.filter((m) => m.id !== member.id &&
|
|
134
|
+
!leadIds.has(m.id) &&
|
|
135
|
+
m.role !== 'orchestrator' &&
|
|
136
|
+
(!m.parentMemberId || m.parentMemberId === member.id || !memberIds.has(m.parentMemberId)));
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Choose the ONE member to route "the team lead" traffic to.
|
|
140
|
+
*
|
|
141
|
+
* Resolution (first match wins):
|
|
142
|
+
* 1. A lead by the rule ({@link getTeamLeadIds}); among several, the one
|
|
143
|
+
* the hierarchy marks as top (`hierarchyLevel === 1 && canDelegate`),
|
|
144
|
+
* else the first.
|
|
145
|
+
* 2. Legacy routing fallback — a member flagged `canDelegate` (hierarchy
|
|
146
|
+
* data imported without `leaderIds` or a lead role). Not a lead by the
|
|
147
|
+
* rule; kept so escalations of such teams still reach someone.
|
|
148
|
+
* 3. First member — better to dispatch to _someone_ than silently drop a
|
|
149
|
+
* `@team` ping. **Emits a warn-log (#332)**.
|
|
28
150
|
*
|
|
29
151
|
* Returns `null` only when the team has no members at all.
|
|
30
152
|
*
|
|
31
153
|
* @param team - The matched team.
|
|
32
|
-
* @returns The
|
|
154
|
+
* @returns The member to dispatch to, or `null` when the team has no members.
|
|
33
155
|
*
|
|
34
156
|
* @example
|
|
35
157
|
* ```typescript
|
|
@@ -41,26 +163,116 @@ export function pickTeamLead(team) {
|
|
|
41
163
|
const members = team.members ?? [];
|
|
42
164
|
if (members.length === 0)
|
|
43
165
|
return null;
|
|
166
|
+
const leads = getTeamLeads(team);
|
|
167
|
+
if (leads.length > 0) {
|
|
168
|
+
return leads.find((m) => m.hierarchyLevel === 1 && m.canDelegate === true) ?? leads[0];
|
|
169
|
+
}
|
|
44
170
|
const hierarchyTl = members.find((m) => m.hierarchyLevel === 1 && m.canDelegate === true);
|
|
45
171
|
if (hierarchyTl)
|
|
46
172
|
return hierarchyTl;
|
|
47
173
|
const anyDelegator = members.find((m) => m.canDelegate === true);
|
|
48
174
|
if (anyDelegator)
|
|
49
175
|
return anyDelegator;
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
// Issue #332: rule-4 fallback — emit a warn so the missing hierarchy
|
|
54
|
-
// data surfaces in observability instead of being invisible. The
|
|
55
|
-
// resolver still returns a member so `@team` pings don't silently
|
|
56
|
-
// drop, but the team owner should fix the underlying hierarchy gap.
|
|
57
|
-
logger.warn('pickTeamLead falling back to first member — team has no canDelegate / team-leader marker', {
|
|
176
|
+
// Issue #332: rule-3 fallback — emit a warn so the missing lead surfaces
|
|
177
|
+
// in observability instead of being invisible.
|
|
178
|
+
teamLogger()?.warn('pickTeamLead falling back to first member — team has no lead (set one with set-team-lead)', {
|
|
58
179
|
teamId: team.id,
|
|
59
180
|
teamName: team.name,
|
|
60
181
|
chosenMemberId: members[0].id,
|
|
61
182
|
memberCount: members.length,
|
|
62
|
-
reason: 'no
|
|
183
|
+
reason: 'no leaderIds and no team-leader / tech-lead member',
|
|
63
184
|
});
|
|
64
185
|
return members[0];
|
|
65
186
|
}
|
|
187
|
+
/**
|
|
188
|
+
* Store the lead rule's answer on the team (idempotent migration, run on
|
|
189
|
+
* every load and save): a team with no usable explicit leads but with
|
|
190
|
+
* lead-role members gets `leaderIds` = those members; `leaderId` always
|
|
191
|
+
* mirrors `leaderIds[0]` for back-compat. The rule's answer never changes —
|
|
192
|
+
* only where it is stored. Dangling explicit ids (members since removed)
|
|
193
|
+
* are dropped when at least one explicit lead remains.
|
|
194
|
+
*
|
|
195
|
+
* @param team - Team (mutated)
|
|
196
|
+
* @returns True when the team changed
|
|
197
|
+
*/
|
|
198
|
+
export function normalizeTeamLeaderIds(team) {
|
|
199
|
+
const ids = getTeamLeadIds(team);
|
|
200
|
+
if (ids.length === 0) {
|
|
201
|
+
// Nothing the rule can use (no member matches). Keep what is stored and
|
|
202
|
+
// only keep the two fields in sync, as before the rule existed.
|
|
203
|
+
if (team.leaderIds && team.leaderIds.length > 0) {
|
|
204
|
+
if (team.leaderId === team.leaderIds[0])
|
|
205
|
+
return false;
|
|
206
|
+
team.leaderId = team.leaderIds[0];
|
|
207
|
+
return true;
|
|
208
|
+
}
|
|
209
|
+
if (team.leaderId && !team.leaderIds) {
|
|
210
|
+
team.leaderIds = [team.leaderId];
|
|
211
|
+
return true;
|
|
212
|
+
}
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
const same = team.leaderIds?.length === ids.length && ids.every((id, i) => team.leaderIds?.[i] === id) && team.leaderId === ids[0];
|
|
216
|
+
if (same)
|
|
217
|
+
return false;
|
|
218
|
+
team.leaderIds = ids;
|
|
219
|
+
team.leaderId = ids[0];
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Make a member a lead of its team (`POST /api/teams/:id/lead`, the
|
|
224
|
+
* `set-team-lead` skill, the dashboard "Make lead" toggle).
|
|
225
|
+
*
|
|
226
|
+
* - `set` (default): the member becomes THE lead. Former leads lose the
|
|
227
|
+
* lead's delegation flag, and members that reported to a former lead now
|
|
228
|
+
* report to the new one.
|
|
229
|
+
* - `add`: the member joins the existing leads.
|
|
230
|
+
*
|
|
231
|
+
* The lead gets `canDelegate = true` (so the in-process delegation guard and
|
|
232
|
+
* hierarchy views agree) and `hierarchyLevel = 1` on hierarchical teams.
|
|
233
|
+
*
|
|
234
|
+
* @param team - Team (mutated)
|
|
235
|
+
* @param memberId - Member to make lead
|
|
236
|
+
* @param mode - `set` or `add`
|
|
237
|
+
* @returns The lead ids before and after
|
|
238
|
+
* @throws Error when the member is not on the team or is the orchestrator
|
|
239
|
+
*/
|
|
240
|
+
export function setTeamLead(team, memberId, mode = 'set') {
|
|
241
|
+
const members = team.members ?? [];
|
|
242
|
+
const lead = members.find((m) => m.id === memberId);
|
|
243
|
+
if (!lead)
|
|
244
|
+
throw new Error(`Member ${memberId} is not on team ${team.name}`);
|
|
245
|
+
if (lead.role === 'orchestrator')
|
|
246
|
+
throw new Error('The orchestrator cannot lead a team');
|
|
247
|
+
const before = getTeamLeadIds(team);
|
|
248
|
+
const after = mode === 'add' ? [...new Set([...before, memberId])] : [memberId];
|
|
249
|
+
const former = new Set(before.filter((id) => !after.includes(id)));
|
|
250
|
+
team.leaderIds = after;
|
|
251
|
+
team.leaderId = after[0];
|
|
252
|
+
lead.canDelegate = true;
|
|
253
|
+
if (team.hierarchical)
|
|
254
|
+
lead.hierarchyLevel = 1;
|
|
255
|
+
if (mode === 'set')
|
|
256
|
+
lead.parentMemberId = undefined;
|
|
257
|
+
for (const m of members) {
|
|
258
|
+
if (m.id === memberId)
|
|
259
|
+
continue;
|
|
260
|
+
if (former.has(m.id)) {
|
|
261
|
+
m.canDelegate = false;
|
|
262
|
+
m.subordinateIds = [];
|
|
263
|
+
if (team.hierarchical) {
|
|
264
|
+
m.hierarchyLevel = 2;
|
|
265
|
+
m.parentMemberId = memberId;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
else if (m.parentMemberId && former.has(m.parentMemberId)) {
|
|
269
|
+
m.parentMemberId = memberId;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
const reports = members.filter((m) => m.parentMemberId === memberId && m.id !== memberId).map((m) => m.id);
|
|
273
|
+
if (reports.length > 0 || lead.subordinateIds)
|
|
274
|
+
lead.subordinateIds = reports;
|
|
275
|
+
const changed = before.length !== after.length || before.some((id, i) => after[i] !== id);
|
|
276
|
+
return { before, after, changed };
|
|
277
|
+
}
|
|
66
278
|
//# sourceMappingURL=team.utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"team.utils.js","sourceRoot":"","sources":["../../../../../backend/src/utils/team.utils.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"team.utils.js","sourceRoot":"","sources":["../../../../../backend/src/utils/team.utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAEtD,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AAEnE;;;;;;GAMG;AACH,SAAS,UAAU;IACjB,IAAI,CAAC;QACH,OAAO,aAAa,CAAC,WAAW,EAAE,EAAE,qBAAqB,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC;IACjF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAYD;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,IAA+B;IACxD,OAAQ,mBAAmB,CAAC,UAAgC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC;AAC5F,CAAC;AAED;;;;;;GAMG;AACH,SAAS,eAAe,CAAC,IAAoB;IAC3C,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACjE,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACnH,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;AAChE,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,cAAc,CAAC,IAAoB;IACjD,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,QAAQ,CAAC;IACzC,OAAO,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AACjF,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,IAAoB,EAAE,MAA8B;IAC7E,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAClD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,IAAU;IACrC,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IACjC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;IACnC,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAmB,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/F,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAoB,EAAE,MAA8C;IACpG,OAAO,MAAM,CAAC,WAAW,KAAK,IAAI,IAAI,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AACjE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAU,EAAE,MAAkB;IAChE,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;IACnC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAS;QAC/B,GAAG,CAAC,MAAM,CAAC,cAAc,IAAI,EAAE,CAAC;QAChC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC1E,CAAC,CAAC;IACH,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC3B,IAAI,QAAQ,CAAC,IAAI,GAAG,CAAC;QAAE,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACxE,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC;QAAE,OAAO,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9C,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACpD,OAAO,OAAO,CAAC,MAAM,CACnB,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE;QAClB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAClB,CAAC,CAAC,IAAI,KAAK,cAAc;QACzB,CAAC,CAAC,CAAC,CAAC,cAAc,IAAI,CAAC,CAAC,cAAc,KAAK,MAAM,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAC5F,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,UAAU,YAAY,CAAC,IAAU;IACrC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;IACnC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEtC,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,KAAK,CAAC,IAAI,CAAC,CAAC,WAAW,KAAK,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC;IACzF,CAAC;IAED,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,KAAK,CAAC,IAAI,CAAC,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC;IAC1F,IAAI,WAAW;QAAE,OAAO,WAAW,CAAC;IACpC,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC;IACjE,IAAI,YAAY;QAAE,OAAO,YAAY,CAAC;IAEtC,yEAAyE;IACzE,+CAA+C;IAC/C,UAAU,EAAE,EAAE,IAAI,CAAC,2FAA2F,EAAE;QAC9G,MAAM,EAAE,IAAI,CAAC,EAAE;QACf,QAAQ,EAAE,IAAI,CAAC,IAAI;QACnB,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE;QAC7B,WAAW,EAAE,OAAO,CAAC,MAAM;QAC3B,MAAM,EAAE,oDAAoD;KAC7D,CAAC,CAAC;IACH,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAAmG;IACxI,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrB,wEAAwE;QACxE,gEAAgE;QAChE,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChD,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;gBAAE,OAAO,KAAK,CAAC;YACtD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YAClC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACrC,IAAI,CAAC,SAAS,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACjC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,EAAE,MAAM,KAAK,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,IAAI,IAAI,CAAC,QAAQ,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;IACnI,IAAI,IAAI;QAAE,OAAO,KAAK,CAAC;IACvB,IAAI,CAAC,SAAS,GAAG,GAAG,CAAC;IACrB,IAAI,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IACvB,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,WAAW,CAAC,IAAU,EAAE,QAAgB,EAAE,OAAwB,KAAK;IACrF,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;IACnC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;IACpD,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,UAAU,QAAQ,mBAAmB,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAC7E,IAAI,IAAI,CAAC,IAAI,KAAK,cAAc;QAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IAEzF,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,KAAK,GAAG,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAChF,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAEnE,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;IACvB,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACzB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;IACxB,IAAI,IAAI,CAAC,YAAY;QAAE,IAAI,CAAC,cAAc,GAAG,CAAC,CAAC;IAC/C,IAAI,IAAI,KAAK,KAAK;QAAE,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;IAEpD,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,EAAE,KAAK,QAAQ;YAAE,SAAS;QAChC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;YACrB,CAAC,CAAC,WAAW,GAAG,KAAK,CAAC;YACtB,CAAC,CAAC,cAAc,GAAG,EAAE,CAAC;YACtB,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;gBACtB,CAAC,CAAC,cAAc,GAAG,CAAC,CAAC;gBACrB,CAAC,CAAC,cAAc,GAAG,QAAQ,CAAC;YAC9B,CAAC;QACH,CAAC;aAAM,IAAI,CAAC,CAAC,cAAc,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC,EAAE,CAAC;YAC5D,CAAC,CAAC,cAAc,GAAG,QAAQ,CAAC;QAC9B,CAAC;IACH,CAAC;IACD,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,KAAK,QAAQ,IAAI,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC3G,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,cAAc;QAAE,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC;IAE7E,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;IAC1F,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AACpC,CAAC"}
|