forgepm 0.7.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 (97) hide show
  1. package/dist/bin/forgepm.d.ts +2 -0
  2. package/dist/bin/forgepm.js +4 -0
  3. package/dist/bin/forgepm.js.map +1 -0
  4. package/dist/src/backends/base.d.ts +23 -0
  5. package/dist/src/backends/base.js +2 -0
  6. package/dist/src/backends/base.js.map +1 -0
  7. package/dist/src/backends/http-utils.d.ts +6 -0
  8. package/dist/src/backends/http-utils.js +36 -0
  9. package/dist/src/backends/http-utils.js.map +1 -0
  10. package/dist/src/backends/jira.d.ts +16 -0
  11. package/dist/src/backends/jira.js +117 -0
  12. package/dist/src/backends/jira.js.map +1 -0
  13. package/dist/src/backends/linear.d.ts +11 -0
  14. package/dist/src/backends/linear.js +85 -0
  15. package/dist/src/backends/linear.js.map +1 -0
  16. package/dist/src/cli/archaeology.d.ts +38 -0
  17. package/dist/src/cli/archaeology.js +182 -0
  18. package/dist/src/cli/archaeology.js.map +1 -0
  19. package/dist/src/cli/index.d.ts +1 -0
  20. package/dist/src/cli/index.js +351 -0
  21. package/dist/src/cli/index.js.map +1 -0
  22. package/dist/src/core/event-bus.d.ts +17 -0
  23. package/dist/src/core/event-bus.js +33 -0
  24. package/dist/src/core/event-bus.js.map +1 -0
  25. package/dist/src/core/event-plugins.d.ts +6 -0
  26. package/dist/src/core/event-plugins.js +2 -0
  27. package/dist/src/core/event-plugins.js.map +1 -0
  28. package/dist/src/core/forge-ops.d.ts +42 -0
  29. package/dist/src/core/forge-ops.js +101 -0
  30. package/dist/src/core/forge-ops.js.map +1 -0
  31. package/dist/src/core/forge.d.ts +44 -0
  32. package/dist/src/core/forge.js +86 -0
  33. package/dist/src/core/forge.js.map +1 -0
  34. package/dist/src/core/schema.d.ts +8 -0
  35. package/dist/src/core/schema.js +139 -0
  36. package/dist/src/core/schema.js.map +1 -0
  37. package/dist/src/core/store.d.ts +24 -0
  38. package/dist/src/core/store.js +155 -0
  39. package/dist/src/core/store.js.map +1 -0
  40. package/dist/src/core/types.d.ts +91 -0
  41. package/dist/src/core/types.js +19 -0
  42. package/dist/src/core/types.js.map +1 -0
  43. package/dist/src/core/version.d.ts +1 -0
  44. package/dist/src/core/version.js +20 -0
  45. package/dist/src/core/version.js.map +1 -0
  46. package/dist/src/github/pull.d.ts +13 -0
  47. package/dist/src/github/pull.js +51 -0
  48. package/dist/src/github/pull.js.map +1 -0
  49. package/dist/src/github/push.d.ts +20 -0
  50. package/dist/src/github/push.js +118 -0
  51. package/dist/src/github/push.js.map +1 -0
  52. package/dist/src/github/setup.d.ts +10 -0
  53. package/dist/src/github/setup.js +112 -0
  54. package/dist/src/github/setup.js.map +1 -0
  55. package/dist/src/github/slack.d.ts +12 -0
  56. package/dist/src/github/slack.js +33 -0
  57. package/dist/src/github/slack.js.map +1 -0
  58. package/dist/src/index.d.ts +14 -0
  59. package/dist/src/index.js +9 -0
  60. package/dist/src/index.js.map +1 -0
  61. package/dist/src/mcp/server.d.ts +5 -0
  62. package/dist/src/mcp/server.js +69 -0
  63. package/dist/src/mcp/server.js.map +1 -0
  64. package/dist/src/mcp/tool-handlers.d.ts +19 -0
  65. package/dist/src/mcp/tool-handlers.js +123 -0
  66. package/dist/src/mcp/tool-handlers.js.map +1 -0
  67. package/dist/src/pm/calibration.d.ts +13 -0
  68. package/dist/src/pm/calibration.js +56 -0
  69. package/dist/src/pm/calibration.js.map +1 -0
  70. package/dist/src/pm/callsheet.d.ts +66 -0
  71. package/dist/src/pm/callsheet.js +91 -0
  72. package/dist/src/pm/callsheet.js.map +1 -0
  73. package/dist/src/pm/drift-detector.d.ts +38 -0
  74. package/dist/src/pm/drift-detector.js +111 -0
  75. package/dist/src/pm/drift-detector.js.map +1 -0
  76. package/dist/src/pm/evm.d.ts +31 -0
  77. package/dist/src/pm/evm.js +58 -0
  78. package/dist/src/pm/evm.js.map +1 -0
  79. package/dist/src/pm/pdca.d.ts +27 -0
  80. package/dist/src/pm/pdca.js +83 -0
  81. package/dist/src/pm/pdca.js.map +1 -0
  82. package/dist/src/pm/recall.d.ts +23 -0
  83. package/dist/src/pm/recall.js +126 -0
  84. package/dist/src/pm/recall.js.map +1 -0
  85. package/dist/src/pm/retrospective.d.ts +35 -0
  86. package/dist/src/pm/retrospective.js +104 -0
  87. package/dist/src/pm/retrospective.js.map +1 -0
  88. package/dist/src/pm/sessions.d.ts +36 -0
  89. package/dist/src/pm/sessions.js +91 -0
  90. package/dist/src/pm/sessions.js.map +1 -0
  91. package/dist/src/pm/tolerances.d.ts +21 -0
  92. package/dist/src/pm/tolerances.js +54 -0
  93. package/dist/src/pm/tolerances.js.map +1 -0
  94. package/dist/src/utils/validation.d.ts +2 -0
  95. package/dist/src/utils/validation.js +8 -0
  96. package/dist/src/utils/validation.js.map +1 -0
  97. package/package.json +55 -0
@@ -0,0 +1,123 @@
1
+ import { getModelTier } from '../core/types.js';
2
+ import { RecallEngine } from '../pm/recall.js';
3
+ import { RetrospectiveEngine } from '../pm/retrospective.js';
4
+ function jsonResult(data) {
5
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
6
+ }
7
+ function errorResult(error, hint) {
8
+ return { content: [{ type: 'text', text: JSON.stringify({ error, hint }, null, 2) }], isError: true };
9
+ }
10
+ export function handleStatus(forge, includeInternal) {
11
+ return jsonResult(forge.getStatus(includeInternal ?? false));
12
+ }
13
+ export function handleStart(forge, taskId, complexity) {
14
+ const result = forge.startTask(taskId, complexity);
15
+ if (!result.ok)
16
+ return errorResult(result.error, result.hint);
17
+ return jsonResult({ ...result.value, next_action: `Work on ${taskId}. Call forge_done when complete.` });
18
+ }
19
+ export function handleDone(forge, taskId, actualTokens, inputTokens, outputTokens, notes) {
20
+ let tokens;
21
+ let tokenSource;
22
+ if (inputTokens !== undefined && outputTokens !== undefined) {
23
+ tokens = inputTokens + outputTokens;
24
+ tokenSource = 'reported';
25
+ }
26
+ else if (actualTokens !== undefined) {
27
+ tokens = actualTokens;
28
+ tokenSource = 'reported';
29
+ }
30
+ else {
31
+ const rows = forge.store.query('SELECT complexity FROM tasks WHERE id = ?', [taskId]);
32
+ tokens = forge.calibration.getEstimate(rows[0]?.complexity ?? 3);
33
+ tokenSource = 'estimated';
34
+ }
35
+ forge.store.run('UPDATE tasks SET token_source = ? WHERE id = ?', [tokenSource, taskId]);
36
+ const result = forge.completeTask(taskId, tokens);
37
+ if (!result.ok)
38
+ return errorResult(result.error, result.hint);
39
+ return jsonResult({ ...result.value, token_source: tokenSource, next_action: 'Call forge_status to see next task.' });
40
+ }
41
+ export function handleSession(forge, action, goal, tokenBudget) {
42
+ if (action === 'start') {
43
+ if (!goal)
44
+ return errorResult('goal is required for action=start');
45
+ return jsonResult(forge.sessions.startSession(goal, tokenBudget ?? 100_000));
46
+ }
47
+ if (action === 'end') {
48
+ try {
49
+ return jsonResult(forge.sessions.endSession());
50
+ }
51
+ catch (err) {
52
+ return errorResult(err instanceof Error ? err.message : String(err));
53
+ }
54
+ }
55
+ return jsonResult(forge.sessions.getSummary() ?? { status: 'no active session' });
56
+ }
57
+ export function handleEscalate(forge, taskId, reason, failureType) {
58
+ const result = forge.failTask(taskId, reason, failureType ?? 'unknown');
59
+ if (!result.ok)
60
+ return errorResult(result.error, result.hint);
61
+ const { escalated, newModel } = result.value;
62
+ return jsonResult({
63
+ taskId, reason, escalated, newModel,
64
+ options: escalated
65
+ ? ['Break task into smaller subtasks', 'Request human review', 'Adjust acceptance criteria']
66
+ : [`Retry with model: ${newModel ?? 'current'}`, 'Refine approach and retry'],
67
+ next_action: escalated ? 'Task blocked — human intervention required.' : `Retry ${taskId} with adjusted approach.`,
68
+ });
69
+ }
70
+ export function handleCreate(forge, type, title, complexity, why, storyId, dependsOn) {
71
+ const prefixMap = { task: 'TASK', story: 'STORY', epic: 'EPIC' };
72
+ const prefix = prefixMap[type] ?? 'TASK';
73
+ const id = forge.store.nextId(prefix);
74
+ const now = new Date().toISOString();
75
+ if (type === 'task') {
76
+ const comp = complexity ?? 3;
77
+ insertTask(forge, id, title, comp, why, storyId, dependsOn, now);
78
+ }
79
+ else if (type === 'story') {
80
+ forge.store.run('INSERT INTO stories (id, title, why, status, created_at) VALUES (?, ?, ?, ?, ?)', [id, title, why ?? '', 'backlog', now]);
81
+ }
82
+ else {
83
+ forge.store.run('INSERT INTO epics (id, title, why, status, created_at) VALUES (?, ?, ?, ?, ?)', [id, title, why ?? '', 'open', now]);
84
+ }
85
+ return jsonResult({ id, type, title, complexity: type === 'task' ? (complexity ?? 3) : undefined, why, status: type === 'epic' ? 'open' : 'backlog' });
86
+ }
87
+ function insertTask(forge, id, title, comp, why, storyId, dependsOn, now) {
88
+ const ts = now ?? new Date().toISOString();
89
+ forge.store.run(`INSERT INTO tasks (id, title, why, complexity, model_tier, story_id, depends_on, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, 'backlog', ?, ?)`, [id, title, why ?? '', comp, getModelTier(comp), storyId ?? '', JSON.stringify(dependsOn ?? []), ts, ts]);
90
+ forge.store.run('INSERT OR IGNORE INTO evm_metrics (task_id, planned_tokens, actual_tokens, updated_at) VALUES (?, ?, 0, ?)', [id, forge.calibration.getEstimate(comp), ts]);
91
+ }
92
+ export function handleRecall(forge, query, entityTypes, statusFilter, limit, includeFailures) {
93
+ const engine = new RecallEngine(forge.store);
94
+ // If includeFailures is true and pdca not already in entityTypes, add it
95
+ let types = entityTypes;
96
+ if (includeFailures && types && !types.includes('pdca')) {
97
+ types = [...types, 'pdca'];
98
+ }
99
+ const results = engine.search({ query, entityTypes: types, statusFilter, limit });
100
+ return jsonResult({
101
+ query, resultCount: results.length, results,
102
+ next_action: results.length > 0 ? 'Use these insights to inform your current task.' : 'No matching results found.',
103
+ });
104
+ }
105
+ export function handleRetro(forge, sessionId, format) {
106
+ const engine = new RetrospectiveEngine(forge.store);
107
+ const report = engine.generate(sessionId);
108
+ if (!report)
109
+ return errorResult('No session found', sessionId ? `No session with id ${sessionId}` : 'No sessions in database');
110
+ if (format === 'markdown')
111
+ return jsonResult({ markdown: engine.formatMarkdown(report) });
112
+ return jsonResult({ ...report, next_action: 'Review lessons and apply recommendations to next session.' });
113
+ }
114
+ export function handleDecompose(_forge, description, maxComplexity, _maxTasks) {
115
+ return jsonResult({
116
+ action: 'agent_decompose',
117
+ description,
118
+ maxComplexity: maxComplexity ?? 5,
119
+ hint: 'Decompose this description into sub-tasks yourself, then call forge_create for each one.',
120
+ next_action: 'Break the description into concrete tasks and create each with forge_create.',
121
+ });
122
+ }
123
+ //# sourceMappingURL=tool-handlers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-handlers.js","sourceRoot":"","sources":["../../../src/mcp/tool-handlers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export interface CalibrationEntry {
2
+ complexity_score: number;
3
+ avg_tokens: number;
4
+ sample_count: number;
5
+ }
6
+ export declare const DEFAULT_CALIBRATION: CalibrationEntry[];
7
+ export declare class CalibrationEngine {
8
+ private data;
9
+ constructor(seedData?: CalibrationEntry[]);
10
+ getEstimate(complexity: number): number;
11
+ update(complexity: number, actualTokens: number): CalibrationEntry;
12
+ getAll(): CalibrationEntry[];
13
+ }
@@ -0,0 +1,56 @@
1
+ const ALPHA = 0.3; // smoothing factor
2
+ export const DEFAULT_CALIBRATION = [
3
+ { complexity_score: 1, avg_tokens: 300, sample_count: 0 },
4
+ { complexity_score: 2, avg_tokens: 500, sample_count: 0 },
5
+ { complexity_score: 3, avg_tokens: 800, sample_count: 0 },
6
+ { complexity_score: 4, avg_tokens: 1200, sample_count: 0 },
7
+ { complexity_score: 5, avg_tokens: 1800, sample_count: 0 },
8
+ { complexity_score: 6, avg_tokens: 2500, sample_count: 0 },
9
+ { complexity_score: 7, avg_tokens: 3500, sample_count: 0 },
10
+ { complexity_score: 8, avg_tokens: 5000, sample_count: 0 },
11
+ { complexity_score: 9, avg_tokens: 7000, sample_count: 0 },
12
+ { complexity_score: 10, avg_tokens: 10000, sample_count: 0 },
13
+ ];
14
+ export class CalibrationEngine {
15
+ data;
16
+ constructor(seedData) {
17
+ this.data = new Map();
18
+ const seed = seedData ?? DEFAULT_CALIBRATION;
19
+ for (const entry of seed) {
20
+ this.data.set(entry.complexity_score, { ...entry });
21
+ }
22
+ }
23
+ getEstimate(complexity) {
24
+ const clamped = Math.max(1, Math.min(10, Math.round(complexity)));
25
+ const entry = this.data.get(clamped);
26
+ return entry?.avg_tokens ?? 1800; // fallback to complexity 5 default
27
+ }
28
+ update(complexity, actualTokens) {
29
+ const clamped = Math.max(1, Math.min(10, Math.round(complexity)));
30
+ const existing = this.data.get(clamped);
31
+ if (existing) {
32
+ const newAvg = ALPHA * actualTokens + (1 - ALPHA) * existing.avg_tokens;
33
+ const updated = {
34
+ complexity_score: clamped,
35
+ avg_tokens: newAvg,
36
+ sample_count: existing.sample_count + 1,
37
+ };
38
+ this.data.set(clamped, updated);
39
+ return updated;
40
+ }
41
+ else {
42
+ // New entry: no prior average, use actual as starting point
43
+ const entry = {
44
+ complexity_score: clamped,
45
+ avg_tokens: actualTokens,
46
+ sample_count: 1,
47
+ };
48
+ this.data.set(clamped, entry);
49
+ return entry;
50
+ }
51
+ }
52
+ getAll() {
53
+ return Array.from(this.data.values()).sort((a, b) => a.complexity_score - b.complexity_score);
54
+ }
55
+ }
56
+ //# sourceMappingURL=calibration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calibration.js","sourceRoot":"","sources":["../../../src/pm/calibration.ts"],"names":[],"mappings":"AAAA,MAAM,KAAK,GAAG,GAAG,CAAC,CAAC,mBAAmB;AAQtC,MAAM,CAAC,MAAM,mBAAmB,GAAuB;IACrD,EAAE,gBAAgB,EAAE,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC,EAAE;IACzD,EAAE,gBAAgB,EAAE,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC,EAAE;IACzD,EAAE,gBAAgB,EAAE,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC,EAAE;IACzD,EAAE,gBAAgB,EAAE,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,EAAE;IAC1D,EAAE,gBAAgB,EAAE,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,EAAE;IAC1D,EAAE,gBAAgB,EAAE,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,EAAE;IAC1D,EAAE,gBAAgB,EAAE,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,EAAE;IAC1D,EAAE,gBAAgB,EAAE,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,EAAE;IAC1D,EAAE,gBAAgB,EAAE,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,EAAE;IAC1D,EAAE,gBAAgB,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,EAAE;CAC7D,CAAC;AAEF,MAAM,OAAO,iBAAiB;IACpB,IAAI,CAAgC;IAE5C,YAAY,QAA6B;QACvC,IAAI,CAAC,IAAI,GAAG,IAAI,GAAG,EAAE,CAAC;QACtB,MAAM,IAAI,GAAG,QAAQ,IAAI,mBAAmB,CAAC;QAC7C,KAAK,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC;YACzB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,gBAAgB,EAAE,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IAED,WAAW,CAAC,UAAkB;QAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAClE,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACrC,OAAO,KAAK,EAAE,UAAU,IAAI,IAAI,CAAC,CAAC,mCAAmC;IACvE,CAAC;IAED,MAAM,CAAC,UAAkB,EAAE,YAAoB;QAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAClE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAExC,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,MAAM,GAAG,KAAK,GAAG,YAAY,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,QAAQ,CAAC,UAAU,CAAC;YACxE,MAAM,OAAO,GAAqB;gBAChC,gBAAgB,EAAE,OAAO;gBACzB,UAAU,EAAE,MAAM;gBAClB,YAAY,EAAE,QAAQ,CAAC,YAAY,GAAG,CAAC;aACxC,CAAC;YACF,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAChC,OAAO,OAAO,CAAC;QACjB,CAAC;aAAM,CAAC;YACN,4DAA4D;YAC5D,MAAM,KAAK,GAAqB;gBAC9B,gBAAgB,EAAE,OAAO;gBACzB,UAAU,EAAE,YAAY;gBACxB,YAAY,EAAE,CAAC;aAChB,CAAC;YACF,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YAC9B,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,MAAM;QACJ,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CACxC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,gBAAgB,GAAG,CAAC,CAAC,gBAAgB,CAClD,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,66 @@
1
+ import type { EvmHealth } from '../core/types.js';
2
+ import type { ToleranceCheckResult } from './tolerances.js';
3
+ export interface TaskBrief {
4
+ id: string;
5
+ title: string;
6
+ status: string;
7
+ complexity: number;
8
+ }
9
+ export interface CallSheet {
10
+ projectName: string;
11
+ goal: string;
12
+ progress: {
13
+ done: number;
14
+ total: number;
15
+ percent: number;
16
+ bar: string;
17
+ };
18
+ tasks: TaskBrief[];
19
+ nextTask: TaskBrief | null;
20
+ issues: string[];
21
+ estimate: string;
22
+ githubUrl?: string;
23
+ }
24
+ export interface InternalMetrics {
25
+ spi: number;
26
+ cpi: number;
27
+ health: EvmHealth;
28
+ signal: string;
29
+ driftAlerts?: Array<{
30
+ driftType: string;
31
+ expected: string;
32
+ actual: string;
33
+ severity: string;
34
+ }>;
35
+ }
36
+ export interface RawTaskInput {
37
+ id: string;
38
+ title: string;
39
+ taskStatus: string;
40
+ complexity: number;
41
+ }
42
+ export interface CallSheetInput {
43
+ projectName: string;
44
+ goal: string;
45
+ tasks: RawTaskInput[];
46
+ tokensRemaining: number;
47
+ avgTokensPerMinute: number;
48
+ toleranceBreaches?: ToleranceCheckResult[];
49
+ escalations?: string[];
50
+ blockers?: string[];
51
+ spi?: number;
52
+ cpi?: number;
53
+ health?: EvmHealth;
54
+ evmSignal?: string;
55
+ githubUrl?: string;
56
+ }
57
+ export declare class CallSheetGenerator {
58
+ generateForHuman(data: CallSheetInput): CallSheet;
59
+ generateForAgent(data: CallSheetInput): CallSheet & {
60
+ internal: InternalMetrics;
61
+ };
62
+ formatProgressBar(percent: number, width?: number): string;
63
+ formatEstimate(remainingTokens: number, avgTokensPerMinute: number): string;
64
+ private buildTaskBriefs;
65
+ private buildIssues;
66
+ }
@@ -0,0 +1,91 @@
1
+ function taskStatusEmoji(taskStatus) {
2
+ switch (taskStatus) {
3
+ case 'done': return '✅ Done';
4
+ case 'in_progress': return '🔄 In Progress';
5
+ case 'blocked': return '🚫 Blocked';
6
+ default: return '⬚ Todo';
7
+ }
8
+ }
9
+ export class CallSheetGenerator {
10
+ generateForHuman(data) {
11
+ const tasks = this.buildTaskBriefs(data.tasks);
12
+ const done = data.tasks.filter((t) => t.taskStatus === 'done').length;
13
+ const total = data.tasks.length;
14
+ const percent = total === 0 ? 0 : (done / total) * 100;
15
+ const issues = this.buildIssues(data);
16
+ const estimate = this.formatEstimate(data.tokensRemaining, data.avgTokensPerMinute);
17
+ const nextTask = tasks.find((t) => t.status !== '✅ Done') ?? null;
18
+ return {
19
+ projectName: data.projectName,
20
+ goal: data.goal,
21
+ progress: {
22
+ done,
23
+ total,
24
+ percent,
25
+ bar: this.formatProgressBar(percent),
26
+ },
27
+ tasks,
28
+ nextTask,
29
+ issues,
30
+ estimate,
31
+ githubUrl: data.githubUrl,
32
+ };
33
+ }
34
+ generateForAgent(data) {
35
+ const sheet = this.generateForHuman(data);
36
+ const internal = {
37
+ spi: data.spi ?? 1.0,
38
+ cpi: data.cpi ?? 1.0,
39
+ health: data.health ?? 'GREEN',
40
+ signal: data.evmSignal ?? 'On track. Continue current approach.',
41
+ };
42
+ return { ...sheet, internal };
43
+ }
44
+ formatProgressBar(percent, width = 10) {
45
+ const filled = Math.round((percent / 100) * width);
46
+ return '█'.repeat(filled) + '░'.repeat(width - filled);
47
+ }
48
+ formatEstimate(remainingTokens, avgTokensPerMinute) {
49
+ if (avgTokensPerMinute <= 0)
50
+ return 'unknown';
51
+ const minutes = Math.round(remainingTokens / avgTokensPerMinute);
52
+ if (minutes < 60)
53
+ return '~' + minutes + ' min remaining';
54
+ const hours = Math.floor(minutes / 60);
55
+ const mins = minutes % 60;
56
+ return '~' + hours + 'h ' + mins + 'm remaining';
57
+ }
58
+ buildTaskBriefs(tasks) {
59
+ return tasks.map((t) => ({
60
+ id: t.id,
61
+ title: t.title,
62
+ status: taskStatusEmoji(t.taskStatus),
63
+ complexity: t.complexity,
64
+ }));
65
+ }
66
+ buildIssues(data) {
67
+ const issues = [];
68
+ if (data.toleranceBreaches) {
69
+ for (const breach of data.toleranceBreaches) {
70
+ if (breach.status === 'breached') {
71
+ issues.push(`Tolerance breached on ${breach.dimension}: ${(breach.actual * 100).toFixed(0)}% of limit (limit ${(breach.upperBound * 100).toFixed(0)}%)`);
72
+ }
73
+ else if (breach.status === 'at_risk') {
74
+ issues.push(`Tolerance at risk on ${breach.dimension}: ${breach.percentUsed.toFixed(0)}% of limit used`);
75
+ }
76
+ }
77
+ }
78
+ if (data.escalations && data.escalations.length > 0) {
79
+ for (const taskId of data.escalations) {
80
+ issues.push(`Task ${taskId} escalated to human: requires manual intervention`);
81
+ }
82
+ }
83
+ if (data.blockers && data.blockers.length > 0) {
84
+ for (const blocker of data.blockers) {
85
+ issues.push(`Blocker: ${blocker}`);
86
+ }
87
+ }
88
+ return issues;
89
+ }
90
+ }
91
+ //# sourceMappingURL=callsheet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"callsheet.js","sourceRoot":"","sources":["../../../src/pm/callsheet.ts"],"names":[],"mappings":"AA0DA,SAAS,eAAe,CAAC,UAAkB;IACzC,QAAQ,UAAU,EAAE,CAAC;QACnB,KAAK,MAAM,CAAC,CAAQ,OAAO,QAAQ,CAAC;QACpC,KAAK,aAAa,CAAC,CAAC,OAAO,gBAAgB,CAAC;QAC5C,KAAK,SAAS,CAAC,CAAK,OAAO,YAAY,CAAC;QACxC,OAAO,CAAC,CAAY,OAAO,QAAQ,CAAC;IACtC,CAAC;AACH,CAAC;AAED,MAAM,OAAO,kBAAkB;IAC7B,gBAAgB,CAAC,IAAoB;QACnC,MAAM,KAAK,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,MAAM,CAAC,CAAC,MAAM,CAAC;QACtE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;QAChC,MAAM,OAAO,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,GAAG,GAAG,CAAC;QAEvD,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAC;QACpF,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,IAAI,IAAI,CAAC;QAElE,OAAO;YACL,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,QAAQ,EAAE;gBACR,IAAI;gBACJ,KAAK;gBACL,OAAO;gBACP,GAAG,EAAE,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC;aACrC;YACD,KAAK;YACL,QAAQ;YACR,MAAM;YACN,QAAQ;YACR,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC;IACJ,CAAC;IAED,gBAAgB,CAAC,IAAoB;QACnC,MAAM,KAAK,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAC1C,MAAM,QAAQ,GAAoB;YAChC,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,GAAG;YACpB,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,GAAG;YACpB,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,OAAO;YAC9B,MAAM,EAAE,IAAI,CAAC,SAAS,IAAI,sCAAsC;SACjE,CAAC;QACF,OAAO,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,CAAC;IAChC,CAAC;IAED,iBAAiB,CAAC,OAAe,EAAE,QAAgB,EAAE;QACnD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,GAAG,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;QACnD,OAAO,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC;IACzD,CAAC;IAED,cAAc,CAAC,eAAuB,EAAE,kBAA0B;QAChE,IAAI,kBAAkB,IAAI,CAAC;YAAE,OAAO,SAAS,CAAC;QAC9C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,GAAG,kBAAkB,CAAC,CAAC;QACjE,IAAI,OAAO,GAAG,EAAE;YAAE,OAAO,GAAG,GAAG,OAAO,GAAG,gBAAgB,CAAC;QAC1D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;QACvC,MAAM,IAAI,GAAG,OAAO,GAAG,EAAE,CAAC;QAC1B,OAAO,GAAG,GAAG,KAAK,GAAG,IAAI,GAAG,IAAI,GAAG,aAAa,CAAC;IACnD,CAAC;IAEO,eAAe,CAAC,KAAqB;QAC3C,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACvB,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,UAAU,CAAC;YACrC,UAAU,EAAE,CAAC,CAAC,UAAU;SACzB,CAAC,CAAC,CAAC;IACN,CAAC;IAEO,WAAW,CAAC,IAAoB;QACtC,MAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC3B,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;gBAC5C,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;oBACjC,MAAM,CAAC,IAAI,CACT,yBAAyB,MAAM,CAAC,SAAS,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC,MAAM,CAAC,UAAU,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAC5I,CAAC;gBACJ,CAAC;qBAAM,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;oBACvC,MAAM,CAAC,IAAI,CACT,wBAAwB,MAAM,CAAC,SAAS,KAAK,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,iBAAiB,CAC5F,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpD,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;gBACtC,MAAM,CAAC,IAAI,CAAC,QAAQ,MAAM,mDAAmD,CAAC,CAAC;YACjF,CAAC;QACH,CAAC;QAED,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9C,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACpC,MAAM,CAAC,IAAI,CAAC,YAAY,OAAO,EAAE,CAAC,CAAC;YACrC,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF"}
@@ -0,0 +1,38 @@
1
+ import type { EventPlugin } from '../core/event-plugins.js';
2
+ import type { DomainEvent } from '../core/types.js';
3
+ import type { OverlayStore } from '../core/store.js';
4
+ export interface DriftThresholds {
5
+ tokenVelocityMultiplier: number;
6
+ failureStreakMax: number;
7
+ wipLimit: number;
8
+ sessionOverrunPercent: number;
9
+ }
10
+ export declare const DEFAULT_DRIFT_THRESHOLDS: DriftThresholds;
11
+ export type DriftType = 'token_velocity' | 'model_mismatch' | 'failure_streak' | 'wip_overflow' | 'session_overrun';
12
+ export interface DriftAlert {
13
+ taskId: string | null;
14
+ driftType: DriftType;
15
+ expected: string;
16
+ actual: string;
17
+ severity: 'warning' | 'critical';
18
+ }
19
+ export declare class DriftDetector implements EventPlugin {
20
+ name: string;
21
+ private thresholds;
22
+ private recentAlerts;
23
+ private rateLimitMs;
24
+ constructor(thresholds?: Partial<DriftThresholds>);
25
+ onEvent(event: DomainEvent, store: OverlayStore): void;
26
+ checkTokenVelocity(taskId: string, store: OverlayStore): DriftAlert[];
27
+ checkModelMismatch(taskId: string, store: OverlayStore): DriftAlert[];
28
+ checkFailureStreak(taskId: string, store: OverlayStore): DriftAlert[];
29
+ checkWipOverflow(store: OverlayStore): DriftAlert[];
30
+ getRecentAlerts(store: OverlayStore, limit?: number): Array<{
31
+ type: string;
32
+ entity_id: string;
33
+ data: string;
34
+ timestamp: string;
35
+ }>;
36
+ private isRateLimited;
37
+ private recordAlert;
38
+ }
@@ -0,0 +1,111 @@
1
+ import { getModelTier } from '../core/types.js';
2
+ export const DEFAULT_DRIFT_THRESHOLDS = {
3
+ tokenVelocityMultiplier: 2.0,
4
+ failureStreakMax: 3,
5
+ wipLimit: 3,
6
+ sessionOverrunPercent: 120,
7
+ };
8
+ export class DriftDetector {
9
+ name = 'drift-detector';
10
+ thresholds;
11
+ recentAlerts = new Map(); // key → timestamp for rate limiting
12
+ rateLimitMs = 60_000; // 1 minute per (taskId, driftType)
13
+ constructor(thresholds) {
14
+ this.thresholds = { ...DEFAULT_DRIFT_THRESHOLDS, ...thresholds };
15
+ }
16
+ onEvent(event, store) {
17
+ const alerts = [];
18
+ if (event.type === 'task.completed') {
19
+ alerts.push(...this.checkTokenVelocity(event.taskId, store));
20
+ alerts.push(...this.checkModelMismatch(event.taskId, store));
21
+ }
22
+ if (event.type === 'task.failed') {
23
+ alerts.push(...this.checkFailureStreak(event.taskId, store));
24
+ }
25
+ if (event.type === 'task.started') {
26
+ alerts.push(...this.checkWipOverflow(store));
27
+ }
28
+ for (const alert of alerts) {
29
+ if (this.isRateLimited(alert))
30
+ continue;
31
+ this.recordAlert(alert);
32
+ store.appendEvent({
33
+ type: 'agent.drift.detected',
34
+ taskId: alert.taskId ?? '',
35
+ driftType: alert.driftType,
36
+ expected: alert.expected,
37
+ actual: alert.actual,
38
+ severity: alert.severity,
39
+ });
40
+ }
41
+ }
42
+ checkTokenVelocity(taskId, store) {
43
+ const row = store.query('SELECT planned_tokens, actual_tokens FROM evm_metrics WHERE task_id = ?', [taskId])[0];
44
+ if (!row || row.planned_tokens === 0)
45
+ return [];
46
+ const ratio = row.actual_tokens / row.planned_tokens;
47
+ if (ratio > this.thresholds.tokenVelocityMultiplier) {
48
+ return [{
49
+ taskId, driftType: 'token_velocity',
50
+ expected: `<= ${row.planned_tokens * this.thresholds.tokenVelocityMultiplier}`,
51
+ actual: String(row.actual_tokens),
52
+ severity: ratio > this.thresholds.tokenVelocityMultiplier * 1.5 ? 'critical' : 'warning',
53
+ }];
54
+ }
55
+ return [];
56
+ }
57
+ checkModelMismatch(taskId, store) {
58
+ const row = store.query('SELECT complexity, model_tier FROM tasks WHERE id = ?', [taskId])[0];
59
+ if (!row)
60
+ return [];
61
+ const expectedTier = getModelTier(row.complexity);
62
+ if (row.model_tier !== expectedTier) {
63
+ return [{
64
+ taskId, driftType: 'model_mismatch',
65
+ expected: expectedTier, actual: row.model_tier,
66
+ severity: 'warning',
67
+ }];
68
+ }
69
+ return [];
70
+ }
71
+ checkFailureStreak(taskId, store) {
72
+ const rows = store.query('SELECT failure_reason FROM pdca_iterations WHERE task_id = ? AND failure_reason IS NOT NULL ORDER BY id DESC', [taskId]);
73
+ if (rows.length >= this.thresholds.failureStreakMax) {
74
+ return [{
75
+ taskId, driftType: 'failure_streak',
76
+ expected: `< ${this.thresholds.failureStreakMax} consecutive failures`,
77
+ actual: `${rows.length} failures`,
78
+ severity: rows.length >= this.thresholds.failureStreakMax * 2 ? 'critical' : 'warning',
79
+ }];
80
+ }
81
+ return [];
82
+ }
83
+ checkWipOverflow(store) {
84
+ const rows = store.query("SELECT COUNT(*) as cnt FROM tasks WHERE status = 'in_progress'");
85
+ const wip = rows[0]?.cnt ?? 0;
86
+ if (wip > this.thresholds.wipLimit) {
87
+ return [{
88
+ taskId: null, driftType: 'wip_overflow',
89
+ expected: `<= ${this.thresholds.wipLimit}`,
90
+ actual: String(wip),
91
+ severity: 'warning',
92
+ }];
93
+ }
94
+ return [];
95
+ }
96
+ getRecentAlerts(store, limit = 10) {
97
+ return store.query("SELECT type, entity_id, data, timestamp FROM events WHERE type = 'agent.drift.detected' ORDER BY id DESC LIMIT ?", [limit]);
98
+ }
99
+ isRateLimited(alert) {
100
+ const key = `${alert.taskId ?? 'global'}:${alert.driftType}`;
101
+ const lastTime = this.recentAlerts.get(key);
102
+ if (lastTime && Date.now() - lastTime < this.rateLimitMs)
103
+ return true;
104
+ return false;
105
+ }
106
+ recordAlert(alert) {
107
+ const key = `${alert.taskId ?? 'global'}:${alert.driftType}`;
108
+ this.recentAlerts.set(key, Date.now());
109
+ }
110
+ }
111
+ //# sourceMappingURL=drift-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drift-detector.js","sourceRoot":"","sources":["../../../src/pm/drift-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import type { EvmHealth } from '../core/types.js';
2
+ import type { CalibrationEngine } from './calibration.js';
3
+ export interface EvmTaskData {
4
+ taskId: string;
5
+ complexity: number;
6
+ plannedTokens: number;
7
+ actualTokens: number;
8
+ status: string;
9
+ }
10
+ export interface EvmMetrics {
11
+ pv: number;
12
+ ev: number;
13
+ ac: number;
14
+ spi: number;
15
+ cpi: number;
16
+ health: EvmHealth;
17
+ signal: string;
18
+ }
19
+ export declare const EVM_ALERTS: {
20
+ SPI_GREEN: number;
21
+ SPI_YELLOW: number;
22
+ CPI_GREEN: number;
23
+ CPI_YELLOW: number;
24
+ };
25
+ export declare class EvmEngine {
26
+ private calibration;
27
+ constructor(calibration: CalibrationEngine);
28
+ calculateMetrics(tasks: EvmTaskData[]): EvmMetrics;
29
+ getTaskPlannedTokens(complexity: number): number;
30
+ generateSignal(spi: number, cpi: number): string;
31
+ }
@@ -0,0 +1,58 @@
1
+ // Alert thresholds — aligned with calculateMetrics health logic
2
+ export const EVM_ALERTS = {
3
+ SPI_GREEN: 0.9, // >= 0.9 = GREEN
4
+ SPI_YELLOW: 0.8, // >= 0.8 = YELLOW
5
+ CPI_GREEN: 0.85, // >= 0.85 = GREEN
6
+ CPI_YELLOW: 0.7, // >= 0.7 = YELLOW (below = RED)
7
+ };
8
+ export class EvmEngine {
9
+ calibration;
10
+ constructor(calibration) {
11
+ this.calibration = calibration;
12
+ }
13
+ calculateMetrics(tasks) {
14
+ // PV = sum of plannedTokens for ALL tasks
15
+ const pv = tasks.reduce((sum, t) => sum + t.plannedTokens, 0);
16
+ // EV = sum of plannedTokens for DONE tasks only (binary: done=PV, not done=0)
17
+ const ev = tasks
18
+ .filter((t) => t.status === 'done')
19
+ .reduce((sum, t) => sum + t.plannedTokens, 0);
20
+ // AC = sum of actualTokens for all tasks with actual > 0
21
+ const ac = tasks
22
+ .filter((t) => t.actualTokens > 0)
23
+ .reduce((sum, t) => sum + t.actualTokens, 0);
24
+ // SPI = EV/PV, handle division by zero → 1.0
25
+ const spi = pv === 0 ? 1.0 : ev / pv;
26
+ // CPI = EV/AC, handle division by zero → 1.0
27
+ const cpi = ac === 0 ? 1.0 : ev / ac;
28
+ // Health: GREEN if SPI>=0.9 && CPI>=0.85, YELLOW if SPI>=0.8 || CPI>=0.7, RED otherwise
29
+ let health;
30
+ if (spi >= 0.9 && cpi >= 0.85) {
31
+ health = 'GREEN';
32
+ }
33
+ else if (spi >= 0.8 || cpi >= 0.7) {
34
+ health = 'YELLOW';
35
+ }
36
+ else {
37
+ health = 'RED';
38
+ }
39
+ const signal = this.generateSignal(spi, cpi);
40
+ return { pv, ev, ac, spi, cpi, health, signal };
41
+ }
42
+ getTaskPlannedTokens(complexity) {
43
+ return this.calibration.getEstimate(complexity);
44
+ }
45
+ generateSignal(spi, cpi) {
46
+ if (spi >= 0.9 && cpi >= 0.85) {
47
+ return 'On track. Continue current approach.';
48
+ }
49
+ if (spi >= 0.8 && cpi >= 0.85) {
50
+ return 'Slightly behind schedule. Consider simplifying.';
51
+ }
52
+ if (spi >= 0.9 && cpi < 0.85) {
53
+ return 'Over budget. Simplify approach or reduce scope.';
54
+ }
55
+ return 'Critical: falling behind and over budget.';
56
+ }
57
+ }
58
+ //# sourceMappingURL=evm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evm.js","sourceRoot":"","sources":["../../../src/pm/evm.ts"],"names":[],"mappings":"AAqBA,gEAAgE;AAChE,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,SAAS,EAAE,GAAG,EAAK,iBAAiB;IACpC,UAAU,EAAE,GAAG,EAAI,kBAAkB;IACrC,SAAS,EAAE,IAAI,EAAI,kBAAkB;IACrC,UAAU,EAAE,GAAG,EAAI,gCAAgC;CACpD,CAAC;AAEF,MAAM,OAAO,SAAS;IACA;IAApB,YAAoB,WAA8B;QAA9B,gBAAW,GAAX,WAAW,CAAmB;IAAG,CAAC;IAEtD,gBAAgB,CAAC,KAAoB;QACnC,0CAA0C;QAC1C,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;QAE9D,8EAA8E;QAC9E,MAAM,EAAE,GAAG,KAAK;aACb,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC;aAClC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;QAEhD,yDAAyD;QACzD,MAAM,EAAE,GAAG,KAAK;aACb,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC;aACjC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;QAE/C,6CAA6C;QAC7C,MAAM,GAAG,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC;QAErC,6CAA6C;QAC7C,MAAM,GAAG,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC;QAErC,wFAAwF;QACxF,IAAI,MAAiB,CAAC;QACtB,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;YAC9B,MAAM,GAAG,OAAO,CAAC;QACnB,CAAC;aAAM,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,EAAE,CAAC;YACpC,MAAM,GAAG,QAAQ,CAAC;QACpB,CAAC;aAAM,CAAC;YACN,MAAM,GAAG,KAAK,CAAC;QACjB,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAE7C,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAClD,CAAC;IAED,oBAAoB,CAAC,UAAkB;QACrC,OAAO,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IAClD,CAAC;IAED,cAAc,CAAC,GAAW,EAAE,GAAW;QACrC,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;YAC9B,OAAO,sCAAsC,CAAC;QAChD,CAAC;QACD,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;YAC9B,OAAO,iDAAiD,CAAC;QAC3D,CAAC;QACD,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,EAAE,CAAC;YAC7B,OAAO,iDAAiD,CAAC;QAC3D,CAAC;QACD,OAAO,2CAA2C,CAAC;IACrD,CAAC;CACF"}