@rasensio/aidlc 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. package/README.md +251 -0
  2. package/capabilities/claude-code.yaml +9 -0
  3. package/capabilities/codex.yaml +8 -0
  4. package/capabilities/cursor.yaml +8 -0
  5. package/capabilities/kiro.yaml +9 -0
  6. package/capabilities/windsurf.yaml +8 -0
  7. package/ci/aidlc-gate.yml +100 -0
  8. package/dist/cli.d.ts +11 -0
  9. package/dist/cli.d.ts.map +1 -0
  10. package/dist/cli.js +39 -0
  11. package/dist/cli.js.map +1 -0
  12. package/dist/commands/add-action.d.ts +83 -0
  13. package/dist/commands/add-action.d.ts.map +1 -0
  14. package/dist/commands/add-action.js +437 -0
  15. package/dist/commands/add-action.js.map +1 -0
  16. package/dist/commands/continue.d.ts +23 -0
  17. package/dist/commands/continue.d.ts.map +1 -0
  18. package/dist/commands/continue.js +238 -0
  19. package/dist/commands/continue.js.map +1 -0
  20. package/dist/commands/discover.d.ts +19 -0
  21. package/dist/commands/discover.d.ts.map +1 -0
  22. package/dist/commands/discover.js +85 -0
  23. package/dist/commands/discover.js.map +1 -0
  24. package/dist/commands/docs.d.ts +25 -0
  25. package/dist/commands/docs.d.ts.map +1 -0
  26. package/dist/commands/docs.js +282 -0
  27. package/dist/commands/docs.js.map +1 -0
  28. package/dist/commands/gate.d.ts +25 -0
  29. package/dist/commands/gate.d.ts.map +1 -0
  30. package/dist/commands/gate.js +168 -0
  31. package/dist/commands/gate.js.map +1 -0
  32. package/dist/commands/init.d.ts +24 -0
  33. package/dist/commands/init.d.ts.map +1 -0
  34. package/dist/commands/init.js +187 -0
  35. package/dist/commands/init.js.map +1 -0
  36. package/dist/commands/review.d.ts +60 -0
  37. package/dist/commands/review.d.ts.map +1 -0
  38. package/dist/commands/review.js +264 -0
  39. package/dist/commands/review.js.map +1 -0
  40. package/dist/commands/setup.d.ts +24 -0
  41. package/dist/commands/setup.d.ts.map +1 -0
  42. package/dist/commands/setup.js +206 -0
  43. package/dist/commands/setup.js.map +1 -0
  44. package/dist/commands/start.d.ts +27 -0
  45. package/dist/commands/start.d.ts.map +1 -0
  46. package/dist/commands/start.js +243 -0
  47. package/dist/commands/start.js.map +1 -0
  48. package/dist/commands/status.d.ts +25 -0
  49. package/dist/commands/status.d.ts.map +1 -0
  50. package/dist/commands/status.js +263 -0
  51. package/dist/commands/status.js.map +1 -0
  52. package/dist/commands/transition.d.ts +30 -0
  53. package/dist/commands/transition.d.ts.map +1 -0
  54. package/dist/commands/transition.js +353 -0
  55. package/dist/commands/transition.js.map +1 -0
  56. package/dist/compile/adapters/claude-code.d.ts +24 -0
  57. package/dist/compile/adapters/claude-code.d.ts.map +1 -0
  58. package/dist/compile/adapters/claude-code.js +271 -0
  59. package/dist/compile/adapters/claude-code.js.map +1 -0
  60. package/dist/compile/adapters/codex.d.ts +19 -0
  61. package/dist/compile/adapters/codex.d.ts.map +1 -0
  62. package/dist/compile/adapters/codex.js +157 -0
  63. package/dist/compile/adapters/codex.js.map +1 -0
  64. package/dist/compile/adapters/cursor.d.ts +21 -0
  65. package/dist/compile/adapters/cursor.d.ts.map +1 -0
  66. package/dist/compile/adapters/cursor.js +181 -0
  67. package/dist/compile/adapters/cursor.js.map +1 -0
  68. package/dist/compile/adapters/index.d.ts +16 -0
  69. package/dist/compile/adapters/index.d.ts.map +1 -0
  70. package/dist/compile/adapters/index.js +26 -0
  71. package/dist/compile/adapters/index.js.map +1 -0
  72. package/dist/compile/adapters/kiro.d.ts +24 -0
  73. package/dist/compile/adapters/kiro.d.ts.map +1 -0
  74. package/dist/compile/adapters/kiro.js +222 -0
  75. package/dist/compile/adapters/kiro.js.map +1 -0
  76. package/dist/compile/adapters/windsurf.d.ts +25 -0
  77. package/dist/compile/adapters/windsurf.d.ts.map +1 -0
  78. package/dist/compile/adapters/windsurf.js +242 -0
  79. package/dist/compile/adapters/windsurf.js.map +1 -0
  80. package/dist/compile/install-plan.d.ts +49 -0
  81. package/dist/compile/install-plan.d.ts.map +1 -0
  82. package/dist/compile/install-plan.js +112 -0
  83. package/dist/compile/install-plan.js.map +1 -0
  84. package/dist/compile/loaders.d.ts +81 -0
  85. package/dist/compile/loaders.d.ts.map +1 -0
  86. package/dist/compile/loaders.js +293 -0
  87. package/dist/compile/loaders.js.map +1 -0
  88. package/dist/compile/merger.d.ts +32 -0
  89. package/dist/compile/merger.d.ts.map +1 -0
  90. package/dist/compile/merger.js +60 -0
  91. package/dist/compile/merger.js.map +1 -0
  92. package/dist/core/gate.d.ts +36 -0
  93. package/dist/core/gate.d.ts.map +1 -0
  94. package/dist/core/gate.js +97 -0
  95. package/dist/core/gate.js.map +1 -0
  96. package/dist/core/index.d.ts +7 -0
  97. package/dist/core/index.d.ts.map +1 -0
  98. package/dist/core/index.js +7 -0
  99. package/dist/core/index.js.map +1 -0
  100. package/dist/core/lifecycle.d.ts +89 -0
  101. package/dist/core/lifecycle.d.ts.map +1 -0
  102. package/dist/core/lifecycle.js +356 -0
  103. package/dist/core/lifecycle.js.map +1 -0
  104. package/dist/core/template-resolver.d.ts +56 -0
  105. package/dist/core/template-resolver.d.ts.map +1 -0
  106. package/dist/core/template-resolver.js +261 -0
  107. package/dist/core/template-resolver.js.map +1 -0
  108. package/dist/core/types.d.ts +527 -0
  109. package/dist/core/types.d.ts.map +1 -0
  110. package/dist/core/types.js +8 -0
  111. package/dist/core/types.js.map +1 -0
  112. package/dist/discover/scanner.d.ts +58 -0
  113. package/dist/discover/scanner.d.ts.map +1 -0
  114. package/dist/discover/scanner.js +772 -0
  115. package/dist/discover/scanner.js.map +1 -0
  116. package/dist/events/event-bus.d.ts +53 -0
  117. package/dist/events/event-bus.d.ts.map +1 -0
  118. package/dist/events/event-bus.js +263 -0
  119. package/dist/events/event-bus.js.map +1 -0
  120. package/dist/events/plugin-hooks.d.ts +44 -0
  121. package/dist/events/plugin-hooks.d.ts.map +1 -0
  122. package/dist/events/plugin-hooks.js +225 -0
  123. package/dist/events/plugin-hooks.js.map +1 -0
  124. package/dist/orchestrator/budget-packer.d.ts +57 -0
  125. package/dist/orchestrator/budget-packer.d.ts.map +1 -0
  126. package/dist/orchestrator/budget-packer.js +70 -0
  127. package/dist/orchestrator/budget-packer.js.map +1 -0
  128. package/dist/orchestrator/config.d.ts +43 -0
  129. package/dist/orchestrator/config.d.ts.map +1 -0
  130. package/dist/orchestrator/config.js +109 -0
  131. package/dist/orchestrator/config.js.map +1 -0
  132. package/dist/orchestrator/endpoint-clients.d.ts +23 -0
  133. package/dist/orchestrator/endpoint-clients.d.ts.map +1 -0
  134. package/dist/orchestrator/endpoint-clients.js +129 -0
  135. package/dist/orchestrator/endpoint-clients.js.map +1 -0
  136. package/dist/orchestrator/orchestrator-loop.d.ts +93 -0
  137. package/dist/orchestrator/orchestrator-loop.d.ts.map +1 -0
  138. package/dist/orchestrator/orchestrator-loop.js +185 -0
  139. package/dist/orchestrator/orchestrator-loop.js.map +1 -0
  140. package/dist/security/confirmation.d.ts +90 -0
  141. package/dist/security/confirmation.d.ts.map +1 -0
  142. package/dist/security/confirmation.js +140 -0
  143. package/dist/security/confirmation.js.map +1 -0
  144. package/dist/setup/setup-compute.d.ts +54 -0
  145. package/dist/setup/setup-compute.d.ts.map +1 -0
  146. package/dist/setup/setup-compute.js +66 -0
  147. package/dist/setup/setup-compute.js.map +1 -0
  148. package/dist/state/snapshot-store.d.ts +79 -0
  149. package/dist/state/snapshot-store.d.ts.map +1 -0
  150. package/dist/state/snapshot-store.js +164 -0
  151. package/dist/state/snapshot-store.js.map +1 -0
  152. package/dist/state/state-recovery.d.ts +87 -0
  153. package/dist/state/state-recovery.d.ts.map +1 -0
  154. package/dist/state/state-recovery.js +274 -0
  155. package/dist/state/state-recovery.js.map +1 -0
  156. package/dist/state/transition-log.d.ts +40 -0
  157. package/dist/state/transition-log.d.ts.map +1 -0
  158. package/dist/state/transition-log.js +83 -0
  159. package/dist/state/transition-log.js.map +1 -0
  160. package/dist/state/yaml-helpers.d.ts +53 -0
  161. package/dist/state/yaml-helpers.d.ts.map +1 -0
  162. package/dist/state/yaml-helpers.js +110 -0
  163. package/dist/state/yaml-helpers.js.map +1 -0
  164. package/examples/.gitkeep +0 -0
  165. package/guidance/accessibility.md +67 -0
  166. package/guidance/api-conventions.md +124 -0
  167. package/guidance/index.yaml +7 -0
  168. package/guidance/secure-defaults.md +71 -0
  169. package/package.json +52 -0
  170. package/phases/.gitkeep +0 -0
  171. package/skills/00-overview.md +74 -0
  172. package/skills/10-ideation.md +45 -0
  173. package/skills/20-requirements.md +54 -0
  174. package/skills/30-design.md +57 -0
  175. package/skills/40-implementation.md +64 -0
  176. package/skills/50-testing.md +60 -0
  177. package/skills/60-deployment.md +63 -0
  178. package/skills/70-maintenance.md +56 -0
  179. package/skills/80-review.md +85 -0
  180. package/skills/81-continue.md +57 -0
  181. package/skills/82-add-action.md +71 -0
  182. package/templates/.gitkeep +0 -0
  183. package/templates/bugfix.yaml +14 -0
  184. package/templates/full-feature.yaml +44 -0
  185. package/templates/micro-task.yaml +11 -0
  186. package/templates/quick-feature.yaml +20 -0
  187. package/templates/spike.yaml +15 -0
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Gate evaluation with exit-code semantics for CI/CD integration.
3
+ *
4
+ * `evaluateGate()` checks whether a phase passes its gate:
5
+ * - Exit 0 (pass: true) iff phase status is 'complete'.
6
+ * - Otherwise, returns structured data naming missing artifacts and unsatisfied criteria.
7
+ *
8
+ * Requirements: 9.1, 9.6
9
+ */
10
+ // ---------------------------------------------------------------------------
11
+ // Gate evaluation
12
+ // ---------------------------------------------------------------------------
13
+ /**
14
+ * Evaluate whether a phase passes its gate check.
15
+ *
16
+ * Exit 0 (pass: true) iff the phase status is 'complete'.
17
+ * Otherwise, returns structured data naming what's missing (Req 9.6).
18
+ *
19
+ * @param phaseName - Name of the phase to check.
20
+ * @param phaseStates - Map of phase name → PhaseState for the instance.
21
+ * @param template - The resolved workflow template defining required artifacts.
22
+ * @returns A GateCheckResult indicating pass/fail with structured details.
23
+ */
24
+ export function evaluateGate(phaseName, phaseStates, template) {
25
+ const state = phaseStates.get(phaseName);
26
+ // Phase not found in state
27
+ if (!state) {
28
+ return {
29
+ pass: false,
30
+ phase: phaseName,
31
+ missingArtifacts: [],
32
+ unsatisfiedCriteria: ['phase not found in instance state'],
33
+ };
34
+ }
35
+ // Phase is complete — gate passes
36
+ if (state.status === 'complete') {
37
+ return {
38
+ pass: true,
39
+ phase: phaseName,
40
+ missingArtifacts: [],
41
+ unsatisfiedCriteria: [],
42
+ };
43
+ }
44
+ // Phase is not complete — gather structured details about what's missing
45
+ const missingArtifacts = getMissingArtifacts(phaseName, state, template);
46
+ const unsatisfiedCriteria = getUnsatisfiedCriteria(state);
47
+ return {
48
+ pass: false,
49
+ phase: phaseName,
50
+ missingArtifacts,
51
+ unsatisfiedCriteria,
52
+ };
53
+ }
54
+ // ---------------------------------------------------------------------------
55
+ // Helpers
56
+ // ---------------------------------------------------------------------------
57
+ /**
58
+ * Determine which required artifacts from the template are not yet 'complete'
59
+ * in the phase state.
60
+ */
61
+ function getMissingArtifacts(phaseName, state, template) {
62
+ // Find the template phase definition
63
+ const templatePhase = template.phases.find((p) => p.name === phaseName);
64
+ if (!templatePhase) {
65
+ // Phase exists in state but not in template — no required artifacts to check
66
+ return [];
67
+ }
68
+ // Build a set of artifact names that are already complete in state
69
+ const completedArtifacts = new Set(state.artifacts
70
+ .filter((a) => a.status === 'complete')
71
+ .map((a) => a.name));
72
+ // Find required artifacts that are not complete
73
+ return templatePhase.required_artifacts
74
+ .filter((decl) => !completedArtifacts.has(decl.name))
75
+ .map((decl) => decl.name);
76
+ }
77
+ /**
78
+ * Describe unsatisfied criteria based on the current phase status.
79
+ */
80
+ function getUnsatisfiedCriteria(state) {
81
+ const criteria = [];
82
+ switch (state.status) {
83
+ case 'pending':
84
+ criteria.push('phase has not been started (status: pending)');
85
+ break;
86
+ case 'in-progress':
87
+ criteria.push('phase is still in progress (status: in-progress)');
88
+ break;
89
+ case 'skipped':
90
+ criteria.push('phase was skipped (status: skipped)');
91
+ break;
92
+ default:
93
+ criteria.push(`phase status is "${state.status}" (expected: complete)`);
94
+ }
95
+ return criteria;
96
+ }
97
+ //# sourceMappingURL=gate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate.js","sourceRoot":"","sources":["../../src/core/gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAsBH,8EAA8E;AAC9E,kBAAkB;AAClB,8EAA8E;AAE9E;;;;;;;;;;GAUG;AACH,MAAM,UAAU,YAAY,CAC1B,SAAiB,EACjB,WAAoC,EACpC,QAA0B;IAE1B,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAEzC,2BAA2B;IAC3B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO;YACL,IAAI,EAAE,KAAK;YACX,KAAK,EAAE,SAAS;YAChB,gBAAgB,EAAE,EAAE;YACpB,mBAAmB,EAAE,CAAC,mCAAmC,CAAC;SAC3D,CAAC;IACJ,CAAC;IAED,kCAAkC;IAClC,IAAI,KAAK,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QAChC,OAAO;YACL,IAAI,EAAE,IAAI;YACV,KAAK,EAAE,SAAS;YAChB,gBAAgB,EAAE,EAAE;YACpB,mBAAmB,EAAE,EAAE;SACxB,CAAC;IACJ,CAAC;IAED,yEAAyE;IACzE,MAAM,gBAAgB,GAAG,mBAAmB,CAAC,SAAS,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;IACzE,MAAM,mBAAmB,GAAG,sBAAsB,CAAC,KAAK,CAAC,CAAC;IAE1D,OAAO;QACL,IAAI,EAAE,KAAK;QACX,KAAK,EAAE,SAAS;QAChB,gBAAgB;QAChB,mBAAmB;KACpB,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E;;;GAGG;AACH,SAAS,mBAAmB,CAC1B,SAAiB,EACjB,KAAiB,EACjB,QAA0B;IAE1B,qCAAqC;IACrC,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CACxC,CAAC,CAAgB,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAC3C,CAAC;IAEF,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,6EAA6E;QAC7E,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,mEAAmE;IACnE,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAChC,KAAK,CAAC,SAAS;SACZ,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,UAAU,CAAC;SACtC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CACtB,CAAC;IAEF,gDAAgD;IAChD,OAAO,aAAa,CAAC,kBAAkB;SACpC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;SACpD,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC;AAED;;GAEG;AACH,SAAS,sBAAsB,CAAC,KAAiB;IAC/C,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,QAAQ,KAAK,CAAC,MAAM,EAAE,CAAC;QACrB,KAAK,SAAS;YACZ,QAAQ,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAC;YAC9D,MAAM;QACR,KAAK,aAAa;YAChB,QAAQ,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;YAClE,MAAM;QACR,KAAK,SAAS;YACZ,QAAQ,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;YACrD,MAAM;QACR;YACE,QAAQ,CAAC,IAAI,CAAC,oBAAoB,KAAK,CAAC,MAAM,wBAAwB,CAAC,CAAC;IAC5E,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,7 @@
1
+ export * from './types.js';
2
+ export * from './template-resolver.js';
3
+ export * from './gate.js';
4
+ export * from './lifecycle.js';
5
+ export * from './lifecycle.js';
6
+ export * from './lifecycle.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,wBAAwB,CAAC;AACvC,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,7 @@
1
+ export * from './types.js';
2
+ export * from './template-resolver.js';
3
+ export * from './gate.js';
4
+ export * from './lifecycle.js';
5
+ export * from './lifecycle.js';
6
+ export * from './lifecycle.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,wBAAwB,CAAC;AACvC,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Pure lifecycle engine functions — completionPercent, isStalled, nextStep, evaluateTransition.
3
+ *
4
+ * These are stateless computations over typed state objects used for
5
+ * progress tracking, observability, continuation resolution, and gate evaluation.
6
+ * (Requirements 3.6, 6.6, 9.3, 11.2, 11.3, 24.6, 26.1, 26.5).
7
+ */
8
+ import type { PhaseState, WorkflowTemplate, InstanceState, NextStep, FindingsIndex, TransitionResult } from './types.js';
9
+ /**
10
+ * Calculate completion percentage for a lifecycle instance.
11
+ *
12
+ * Integer 0-100, floor of: (completed required artifacts) / (total required artifacts)
13
+ * across all applicable phases (filtered by scope).
14
+ *
15
+ * Algorithm:
16
+ * 1. Get applicable phases from the template (accounting for scope via phasesForScope)
17
+ * 2. Count total required artifacts across all applicable phases
18
+ * 3. Count completed artifacts (status === 'complete') from phase states
19
+ * 4. Return Math.floor((completed / total) * 100), or 0 if total is 0
20
+ *
21
+ * @param phaseStates - Map of phase name to PhaseState for this instance.
22
+ * @param template - The resolved workflow template (no `extends`).
23
+ * @param scope - The cycle scope to determine applicable phases.
24
+ * @returns Integer 0-100 representing completion percentage.
25
+ */
26
+ export declare function completionPercent(phaseStates: Map<string, PhaseState>, template: WorkflowTemplate, scope?: InstanceState['scope']): number;
27
+ /**
28
+ * Determine if an instance is stalled.
29
+ *
30
+ * Stalled = current phase has been active longer than thresholdDays
31
+ * AND completionPercent < 100%.
32
+ * Never stalled at 100% — a completed instance is never flagged regardless
33
+ * of how long its current phase has been active.
34
+ *
35
+ * @param state - The instance state (provides current_phase and scope).
36
+ * @param phaseStates - Map of phase name to PhaseState for this instance.
37
+ * @param template - The resolved workflow template.
38
+ * @param now - Current time for age calculation.
39
+ * @param thresholdDays - Number of days before a phase is considered stalled.
40
+ * @returns true if the instance is stalled, false otherwise.
41
+ */
42
+ export declare function isStalled(state: InstanceState, phaseStates: Map<string, PhaseState>, template: WorkflowTemplate, now: Date, thresholdDays: number): boolean;
43
+ /**
44
+ * Continuation resolver — deterministic function of template and state.
45
+ *
46
+ * Returns the next action the instance should take:
47
+ * - `{ kind: 'artifact', phase, artifact }` — produce this artifact next
48
+ * - `{ kind: 'phase', phase }` — enter this phase next
49
+ * - `{ kind: 'complete' }` — all phases and artifacts are done
50
+ *
51
+ * Algorithm:
52
+ * 1. Get the resolved phases for the current scope from the template.
53
+ * 2. Find the current phase in the resolved list.
54
+ * 3. In the current phase, find the first required artifact with status !== 'complete'.
55
+ * → return `{ kind: 'artifact', phase: currentPhase, artifact: artifactName }`
56
+ * 4. If all required artifacts in the current phase are complete, find the next
57
+ * pending phase (status not 'complete' and not 'skipped').
58
+ * → return `{ kind: 'phase', phase: nextPhaseName }`
59
+ * 5. If no pending phases remain, return `{ kind: 'complete' }`.
60
+ *
61
+ * @param state - The current instance state.
62
+ * @param phaseStates - Map of phase name → PhaseState for all tracked phases.
63
+ * @param template - The fully resolved workflow template (no `extends`).
64
+ * @returns The next step the instance should take.
65
+ */
66
+ export declare function nextStep(state: InstanceState, phaseStates: Map<string, PhaseState>, template: WorkflowTemplate): NextStep;
67
+ /**
68
+ * Gate chain — evaluates whether a phase transition is allowed.
69
+ * Returns Allowed or Blocked (with EVERY unsatisfied condition).
70
+ *
71
+ * Gate evaluation order:
72
+ * 1. Required artifacts of the current phase all "complete"
73
+ * 2. Review gate (if template configures one for this phase): no critical+open findings
74
+ * 3. Ownership guard: warn + require override if actor ≠ recorded owner
75
+ * 4. Deployment entry: every preceding required phase has recorded status "complete" (from state only)
76
+ * 5. Blocking actions (placeholder — currently no-op)
77
+ *
78
+ * A blocked attempt reports every unsatisfied condition (Req 4.4).
79
+ *
80
+ * @param state - Current instance state.
81
+ * @param phaseStates - Map of phase name → PhaseState for all phases in the instance.
82
+ * @param template - The resolved workflow template (no `extends`).
83
+ * @param actor - Identity of the user/agent attempting the transition.
84
+ * @param findings - Findings index keyed by artifact name.
85
+ * @param override - If true, suppresses the ownership violation.
86
+ * @returns TransitionResult — `{ allowed: true }` or `{ allowed: false, violations: [...] }`.
87
+ */
88
+ export declare function evaluateTransition(state: InstanceState, phaseStates: Map<string, PhaseState>, template: WorkflowTemplate, actor: string, findings: FindingsIndex, override?: boolean): TransitionResult;
89
+ //# sourceMappingURL=lifecycle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../../src/core/lifecycle.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,UAAU,EACV,gBAAgB,EAChB,aAAa,EACb,QAAQ,EAER,aAAa,EACb,gBAAgB,EAEjB,MAAM,YAAY,CAAC;AAOpB;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,EACpC,QAAQ,EAAE,gBAAgB,EAC1B,KAAK,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,GAC7B,MAAM,CA2BR;AAMD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,SAAS,CACvB,KAAK,EAAE,aAAa,EACpB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,EACpC,QAAQ,EAAE,gBAAgB,EAC1B,GAAG,EAAE,IAAI,EACT,aAAa,EAAE,MAAM,GACpB,OAAO,CAeT;AAOD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,QAAQ,CACtB,KAAK,EAAE,aAAa,EACpB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,EACpC,QAAQ,EAAE,gBAAgB,GACzB,QAAQ,CA+CV;AA8ED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,aAAa,EACpB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,EACpC,QAAQ,EAAE,gBAAgB,EAC1B,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,aAAa,EACvB,QAAQ,CAAC,EAAE,OAAO,GACjB,gBAAgB,CAiClB"}
@@ -0,0 +1,356 @@
1
+ /**
2
+ * Pure lifecycle engine functions — completionPercent, isStalled, nextStep, evaluateTransition.
3
+ *
4
+ * These are stateless computations over typed state objects used for
5
+ * progress tracking, observability, continuation resolution, and gate evaluation.
6
+ * (Requirements 3.6, 6.6, 9.3, 11.2, 11.3, 24.6, 26.1, 26.5).
7
+ */
8
+ import { phasesForScope } from './template-resolver.js';
9
+ // ---------------------------------------------------------------------------
10
+ // completionPercent (Req 11.2)
11
+ // ---------------------------------------------------------------------------
12
+ /**
13
+ * Calculate completion percentage for a lifecycle instance.
14
+ *
15
+ * Integer 0-100, floor of: (completed required artifacts) / (total required artifacts)
16
+ * across all applicable phases (filtered by scope).
17
+ *
18
+ * Algorithm:
19
+ * 1. Get applicable phases from the template (accounting for scope via phasesForScope)
20
+ * 2. Count total required artifacts across all applicable phases
21
+ * 3. Count completed artifacts (status === 'complete') from phase states
22
+ * 4. Return Math.floor((completed / total) * 100), or 0 if total is 0
23
+ *
24
+ * @param phaseStates - Map of phase name to PhaseState for this instance.
25
+ * @param template - The resolved workflow template (no `extends`).
26
+ * @param scope - The cycle scope to determine applicable phases.
27
+ * @returns Integer 0-100 representing completion percentage.
28
+ */
29
+ export function completionPercent(phaseStates, template, scope) {
30
+ const effectiveScope = scope ?? template.scope;
31
+ const applicablePhases = phasesForScope(template, effectiveScope);
32
+ let totalRequired = 0;
33
+ let completedCount = 0;
34
+ for (const templatePhase of applicablePhases) {
35
+ totalRequired += templatePhase.required_artifacts.length;
36
+ const phaseState = phaseStates.get(templatePhase.name);
37
+ if (!phaseState)
38
+ continue;
39
+ for (const artifact of phaseState.artifacts) {
40
+ // Only count artifacts that are declared as required in the template
41
+ const isRequired = templatePhase.required_artifacts.some((ra) => ra.name === artifact.name);
42
+ if (isRequired && artifact.status === 'complete') {
43
+ completedCount++;
44
+ }
45
+ }
46
+ }
47
+ if (totalRequired === 0)
48
+ return 0;
49
+ return Math.floor((completedCount / totalRequired) * 100);
50
+ }
51
+ // ---------------------------------------------------------------------------
52
+ // isStalled (Req 11.3)
53
+ // ---------------------------------------------------------------------------
54
+ /**
55
+ * Determine if an instance is stalled.
56
+ *
57
+ * Stalled = current phase has been active longer than thresholdDays
58
+ * AND completionPercent < 100%.
59
+ * Never stalled at 100% — a completed instance is never flagged regardless
60
+ * of how long its current phase has been active.
61
+ *
62
+ * @param state - The instance state (provides current_phase and scope).
63
+ * @param phaseStates - Map of phase name to PhaseState for this instance.
64
+ * @param template - The resolved workflow template.
65
+ * @param now - Current time for age calculation.
66
+ * @param thresholdDays - Number of days before a phase is considered stalled.
67
+ * @returns true if the instance is stalled, false otherwise.
68
+ */
69
+ export function isStalled(state, phaseStates, template, now, thresholdDays) {
70
+ // Never stalled at 100% completion
71
+ const percent = completionPercent(phaseStates, template, state.scope);
72
+ if (percent >= 100)
73
+ return false;
74
+ // Find the current phase state
75
+ const currentPhaseState = phaseStates.get(state.current_phase);
76
+ if (!currentPhaseState || !currentPhaseState.entered_at)
77
+ return false;
78
+ // Calculate how long the phase has been active
79
+ const enteredAt = new Date(currentPhaseState.entered_at);
80
+ const elapsedMs = now.getTime() - enteredAt.getTime();
81
+ const elapsedDays = elapsedMs / (1000 * 60 * 60 * 24);
82
+ return elapsedDays > thresholdDays;
83
+ }
84
+ // ---------------------------------------------------------------------------
85
+ // nextStep — Continuation Resolver (Req 26.1, 26.5)
86
+ // ---------------------------------------------------------------------------
87
+ /**
88
+ * Continuation resolver — deterministic function of template and state.
89
+ *
90
+ * Returns the next action the instance should take:
91
+ * - `{ kind: 'artifact', phase, artifact }` — produce this artifact next
92
+ * - `{ kind: 'phase', phase }` — enter this phase next
93
+ * - `{ kind: 'complete' }` — all phases and artifacts are done
94
+ *
95
+ * Algorithm:
96
+ * 1. Get the resolved phases for the current scope from the template.
97
+ * 2. Find the current phase in the resolved list.
98
+ * 3. In the current phase, find the first required artifact with status !== 'complete'.
99
+ * → return `{ kind: 'artifact', phase: currentPhase, artifact: artifactName }`
100
+ * 4. If all required artifacts in the current phase are complete, find the next
101
+ * pending phase (status not 'complete' and not 'skipped').
102
+ * → return `{ kind: 'phase', phase: nextPhaseName }`
103
+ * 5. If no pending phases remain, return `{ kind: 'complete' }`.
104
+ *
105
+ * @param state - The current instance state.
106
+ * @param phaseStates - Map of phase name → PhaseState for all tracked phases.
107
+ * @param template - The fully resolved workflow template (no `extends`).
108
+ * @returns The next step the instance should take.
109
+ */
110
+ export function nextStep(state, phaseStates, template) {
111
+ // Step 1: Get applicable phases for the current scope
112
+ const applicablePhases = phasesForScope(template, state.scope);
113
+ if (applicablePhases.length === 0) {
114
+ return { kind: 'complete' };
115
+ }
116
+ // Step 2: Find the current phase in the applicable phases list
117
+ const currentPhaseIndex = applicablePhases.findIndex((p) => p.name === state.current_phase);
118
+ // If current phase is found, check for incomplete artifacts in it
119
+ if (currentPhaseIndex !== -1) {
120
+ const currentTemplatePhase = applicablePhases[currentPhaseIndex];
121
+ const currentPhaseState = phaseStates.get(state.current_phase);
122
+ // Step 3: Find the first incomplete required artifact in the current phase
123
+ const incompleteArtifact = findFirstIncompleteArtifact(currentTemplatePhase, currentPhaseState);
124
+ if (incompleteArtifact !== null) {
125
+ return {
126
+ kind: 'artifact',
127
+ phase: state.current_phase,
128
+ artifact: incompleteArtifact,
129
+ };
130
+ }
131
+ }
132
+ // Step 4: All artifacts in current phase are complete (or current phase not found).
133
+ // Find the next pending phase that is not the current phase.
134
+ const nextPendingPhase = findNextPendingPhase(applicablePhases, phaseStates, state.current_phase);
135
+ if (nextPendingPhase !== null) {
136
+ return { kind: 'phase', phase: nextPendingPhase };
137
+ }
138
+ // Step 5: No pending phases remain — all done.
139
+ return { kind: 'complete' };
140
+ }
141
+ /**
142
+ * Find the first required artifact in a template phase that is not yet complete.
143
+ *
144
+ * @returns The artifact name, or null if all required artifacts are complete.
145
+ */
146
+ function findFirstIncompleteArtifact(templatePhase, phaseState) {
147
+ if (templatePhase.required_artifacts.length === 0) {
148
+ return null;
149
+ }
150
+ // Build a set of completed artifact names from the phase state
151
+ const completedArtifacts = new Set();
152
+ if (phaseState) {
153
+ for (const artifact of phaseState.artifacts) {
154
+ if (artifact.status === 'complete') {
155
+ completedArtifacts.add(artifact.name);
156
+ }
157
+ }
158
+ }
159
+ // Find the first required artifact that is not complete
160
+ for (const decl of templatePhase.required_artifacts) {
161
+ if (!completedArtifacts.has(decl.name)) {
162
+ return decl.name;
163
+ }
164
+ }
165
+ return null;
166
+ }
167
+ /**
168
+ * Find the next phase that is not yet complete or skipped, excluding the
169
+ * current phase (since we already checked its artifacts).
170
+ *
171
+ * Iterates through applicable phases in order. A phase is "pending" if
172
+ * its phase state status is not 'complete' and not 'skipped', or if
173
+ * no phase state exists for it yet (implicitly pending).
174
+ *
175
+ * @param currentPhase - The current phase to exclude from results.
176
+ * @returns The name of the next pending phase, or null if all are done/skipped.
177
+ */
178
+ function findNextPendingPhase(applicablePhases, phaseStates, currentPhase) {
179
+ for (const templatePhase of applicablePhases) {
180
+ // Skip the current phase — its artifacts are already handled
181
+ if (templatePhase.name === currentPhase) {
182
+ continue;
183
+ }
184
+ const ps = phaseStates.get(templatePhase.name);
185
+ // No phase state → phase hasn't started → it's pending
186
+ if (!ps) {
187
+ return templatePhase.name;
188
+ }
189
+ // Phase exists but is neither complete nor skipped → still pending
190
+ if (ps.status !== 'complete' && ps.status !== 'skipped') {
191
+ return templatePhase.name;
192
+ }
193
+ }
194
+ return null;
195
+ }
196
+ // ---------------------------------------------------------------------------
197
+ // evaluateTransition (Req 3.6, 6.6, 9.3, 24.6)
198
+ // ---------------------------------------------------------------------------
199
+ /**
200
+ * Gate chain — evaluates whether a phase transition is allowed.
201
+ * Returns Allowed or Blocked (with EVERY unsatisfied condition).
202
+ *
203
+ * Gate evaluation order:
204
+ * 1. Required artifacts of the current phase all "complete"
205
+ * 2. Review gate (if template configures one for this phase): no critical+open findings
206
+ * 3. Ownership guard: warn + require override if actor ≠ recorded owner
207
+ * 4. Deployment entry: every preceding required phase has recorded status "complete" (from state only)
208
+ * 5. Blocking actions (placeholder — currently no-op)
209
+ *
210
+ * A blocked attempt reports every unsatisfied condition (Req 4.4).
211
+ *
212
+ * @param state - Current instance state.
213
+ * @param phaseStates - Map of phase name → PhaseState for all phases in the instance.
214
+ * @param template - The resolved workflow template (no `extends`).
215
+ * @param actor - Identity of the user/agent attempting the transition.
216
+ * @param findings - Findings index keyed by artifact name.
217
+ * @param override - If true, suppresses the ownership violation.
218
+ * @returns TransitionResult — `{ allowed: true }` or `{ allowed: false, violations: [...] }`.
219
+ */
220
+ export function evaluateTransition(state, phaseStates, template, actor, findings, override) {
221
+ const violations = [];
222
+ // Find the current phase in the resolved template
223
+ const currentPhaseName = state.current_phase;
224
+ const applicablePhases = phasesForScope(template, state.scope);
225
+ const currentTemplatePhase = applicablePhases.find((p) => p.name === currentPhaseName);
226
+ // Gate 1: Required artifacts — all must have status 'complete'
227
+ if (currentTemplatePhase) {
228
+ const currentPhaseState = phaseStates.get(currentPhaseName);
229
+ checkRequiredArtifacts(currentTemplatePhase, currentPhaseState, violations);
230
+ }
231
+ // Gate 2: Review gate — if template configures adversarial-review for this phase
232
+ checkReviewGate(template, currentPhaseName, findings, violations);
233
+ // Gate 3: Ownership guard — actor must match phase owner (unless override)
234
+ checkOwnership(phaseStates, currentPhaseName, actor, override, violations);
235
+ // Gate 4: Deployment entry — all preceding required phases must be complete
236
+ checkDeploymentEntry(applicablePhases, currentPhaseName, phaseStates, violations);
237
+ // Gate 5: Blocking actions (placeholder — no implementation yet)
238
+ // Future: check enabled blocking actions and add violations if any fail.
239
+ if (violations.length === 0) {
240
+ return { allowed: true };
241
+ }
242
+ return { allowed: false, violations };
243
+ }
244
+ // ---------------------------------------------------------------------------
245
+ // Gate helpers
246
+ // ---------------------------------------------------------------------------
247
+ /**
248
+ * Check that all required artifacts in the current phase have status 'complete'.
249
+ */
250
+ function checkRequiredArtifacts(templatePhase, phaseState, violations) {
251
+ if (!templatePhase.required_artifacts || templatePhase.required_artifacts.length === 0) {
252
+ return;
253
+ }
254
+ if (!phaseState) {
255
+ // Phase state doesn't exist — all artifacts are missing
256
+ for (const art of templatePhase.required_artifacts) {
257
+ violations.push({
258
+ gate: 'required-artifacts',
259
+ reason: `required artifact "${art.name}" is missing (no phase state)`,
260
+ });
261
+ }
262
+ return;
263
+ }
264
+ for (const requiredArt of templatePhase.required_artifacts) {
265
+ const tracked = phaseState.artifacts.find((a) => a.name === requiredArt.name);
266
+ if (!tracked || tracked.status !== 'complete') {
267
+ const status = tracked ? tracked.status : 'not-started';
268
+ violations.push({
269
+ gate: 'required-artifacts',
270
+ reason: `required artifact "${requiredArt.name}" is not complete (status: ${status})`,
271
+ });
272
+ }
273
+ }
274
+ }
275
+ /**
276
+ * If the template has an adversarial-review gate for the current phase,
277
+ * check that no finding with severity 'critical' and status 'open' exists.
278
+ */
279
+ function checkReviewGate(template, currentPhaseName, findings, violations) {
280
+ const reviewGatePhases = template.gates?.['adversarial-review'];
281
+ if (!reviewGatePhases || !reviewGatePhases.includes(currentPhaseName)) {
282
+ return;
283
+ }
284
+ // Review gate is configured for this phase — check findings
285
+ const allFindings = Object.values(findings).flat();
286
+ // If no findings exist at all (no review has been done), block
287
+ if (allFindings.length === 0) {
288
+ violations.push({
289
+ gate: 'review-gate',
290
+ reason: `review gate requires a completed review for phase "${currentPhaseName}" but no findings exist`,
291
+ });
292
+ return;
293
+ }
294
+ // Block on any critical+open finding
295
+ const criticalOpen = allFindings.filter((f) => f.severity === 'critical' && f.status === 'open');
296
+ for (const finding of criticalOpen) {
297
+ violations.push({
298
+ gate: 'review-gate',
299
+ reason: `critical finding "${finding.id}" is still open: ${finding.title}`,
300
+ });
301
+ }
302
+ }
303
+ /**
304
+ * If phase ownership is set and actor ≠ owner, add an ownership violation
305
+ * (unless override is true).
306
+ */
307
+ function checkOwnership(phaseStates, currentPhaseName, actor, override, violations) {
308
+ if (override) {
309
+ return;
310
+ }
311
+ const phaseState = phaseStates.get(currentPhaseName);
312
+ if (!phaseState || !phaseState.owner) {
313
+ return;
314
+ }
315
+ if (phaseState.owner !== actor) {
316
+ violations.push({
317
+ gate: 'ownership',
318
+ reason: `phase "${currentPhaseName}" is owned by "${phaseState.owner}" but transition attempted by "${actor}"; use override to proceed`,
319
+ });
320
+ }
321
+ }
322
+ /**
323
+ * If the next phase is 'deployment', verify that all preceding required phases
324
+ * have recorded status 'complete' or 'skipped' (from state only, not disk).
325
+ * The current phase is excluded from this check since its completion is
326
+ * validated by the required-artifacts gate.
327
+ */
328
+ function checkDeploymentEntry(applicablePhases, currentPhaseName, phaseStates, violations) {
329
+ // Find the index of the current phase
330
+ const currentIdx = applicablePhases.findIndex((p) => p.name === currentPhaseName);
331
+ if (currentIdx === -1) {
332
+ return;
333
+ }
334
+ // Determine the next phase (the target of this transition)
335
+ const nextIdx = currentIdx + 1;
336
+ if (nextIdx >= applicablePhases.length) {
337
+ return;
338
+ }
339
+ const nextPhase = applicablePhases[nextIdx];
340
+ if (nextPhase.name !== 'deployment') {
341
+ return;
342
+ }
343
+ // Target is deployment — verify all preceding required phases (except current) are complete
344
+ for (let i = 0; i < currentIdx; i++) {
345
+ const phase = applicablePhases[i];
346
+ const ps = phaseStates.get(phase.name);
347
+ if (!ps || (ps.status !== 'complete' && ps.status !== 'skipped')) {
348
+ const status = ps ? ps.status : 'pending';
349
+ violations.push({
350
+ gate: 'deployment-entry',
351
+ reason: `phase "${phase.name}" must be complete before entering deployment (status: ${status})`,
352
+ });
353
+ }
354
+ }
355
+ }
356
+ //# sourceMappingURL=lifecycle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../src/core/lifecycle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Template resolution — inheritance, cycle-scope phase applicability.
3
+ *
4
+ * - `resolveTemplate()` applies the full inheritance chain (remove/override/add).
5
+ * - `loadTemplates()` loads all template YAML files from a directory.
6
+ * - `phasesForScope()` filters phases by cycle scope.
7
+ *
8
+ * Requirements: 8.1, 8.5, 5.1, 5.2
9
+ */
10
+ import type { WorkflowTemplate, TemplatePhase, CycleScope } from './types.js';
11
+ /**
12
+ * Error thrown when template resolution encounters a problem
13
+ * (cycle, missing parent, invalid insertion point).
14
+ */
15
+ export declare class TemplateResolutionError extends Error {
16
+ constructor(message: string);
17
+ }
18
+ /**
19
+ * Get the applicable phases for a given cycle scope.
20
+ *
21
+ * Filters the resolved template's phases to include only those whose name
22
+ * appears in the scope's allowed phase set. Custom (non-core) phase names
23
+ * pass through for all scopes (they are never filtered out by scope rules).
24
+ *
25
+ * @param resolvedTemplate - A fully resolved template (no `extends`).
26
+ * @param scope - The cycle scope to filter by.
27
+ * @returns The subset of template phases applicable to the given scope.
28
+ */
29
+ export declare function phasesForScope(resolvedTemplate: WorkflowTemplate, scope: CycleScope): TemplatePhase[];
30
+ /**
31
+ * Resolve a template by applying its inheritance chain.
32
+ *
33
+ * Resolution algorithm:
34
+ * 1. If no `extends` → template is already resolved (return a copy with
35
+ * inheritance fields cleared).
36
+ * 2. Load parent template, resolve it recursively (cycle-detected).
37
+ * 3. Start with parent's resolved phases.
38
+ * 4. Apply `remove`: filter out listed phases.
39
+ * 5. Apply `override`: for each phase name in override map, merge fields.
40
+ * 6. Apply `add`: insert new phases at declared positions (before/after).
41
+ *
42
+ * @param template - The template to resolve.
43
+ * @param allTemplates - Map of all available templates by name.
44
+ * @returns A fully resolved WorkflowTemplate (no `extends`, all phases concrete).
45
+ * @throws {TemplateResolutionError} On circular inheritance or missing parent.
46
+ */
47
+ export declare function resolveTemplate(template: WorkflowTemplate, allTemplates: Map<string, WorkflowTemplate>): WorkflowTemplate;
48
+ /**
49
+ * Load all templates from a directory. Each `.yaml` or `.yml` file is parsed
50
+ * as a WorkflowTemplate. Invalid files are skipped with a warning to stderr.
51
+ *
52
+ * @param templateDir - Path to the directory containing template YAML files.
53
+ * @returns A Map of template name → WorkflowTemplate.
54
+ */
55
+ export declare function loadTemplates(templateDir: string): Map<string, WorkflowTemplate>;
56
+ //# sourceMappingURL=template-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-resolver.d.ts","sourceRoot":"","sources":["../../src/core/template-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EACV,gBAAgB,EAChB,aAAa,EAGb,UAAU,EAEX,MAAM,YAAY,CAAC;AAMpB;;;GAGG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;gBACpC,OAAO,EAAE,MAAM;CAI5B;AAwBD;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAC5B,gBAAgB,EAAE,gBAAgB,EAClC,KAAK,EAAE,UAAU,GAChB,aAAa,EAAE,CAUjB;AAMD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,gBAAgB,EAC1B,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAC1C,gBAAgB,CAElB;AA6ID;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CA+BhF"}