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,27 @@
1
+ import type { PdcaPhase, ModelTier, Result } from '../core/types.js';
2
+ export interface PdcaState {
3
+ taskId: string;
4
+ currentPhase: PdcaPhase;
5
+ iteration: number;
6
+ maxRetries: number;
7
+ modelTier: ModelTier;
8
+ escalationCount: number;
9
+ failures: PdcaFailure[];
10
+ }
11
+ export interface PdcaFailure {
12
+ iteration: number;
13
+ phase: PdcaPhase;
14
+ reason: string;
15
+ modelUsed: ModelTier;
16
+ timestamp: string;
17
+ }
18
+ export type FailureType = 'reasoning' | 'prompt' | 'task_definition' | 'unknown';
19
+ export declare class PdcaTracker {
20
+ private states;
21
+ startTask(taskId: string, complexity: number, maxRetries?: number): PdcaState;
22
+ recordFailure(taskId: string, reason: string, failureType: FailureType): Result<PdcaState>;
23
+ completeTask(taskId: string): Result<PdcaState>;
24
+ getState(taskId: string): PdcaState | undefined;
25
+ shouldEscalateModel(state: PdcaState): boolean;
26
+ private nextModelTier;
27
+ }
@@ -0,0 +1,83 @@
1
+ import { getModelTier } from '../core/types.js';
2
+ const PHASE_ORDER = ['plan', 'do', 'check', 'act', 'done'];
3
+ export class PdcaTracker {
4
+ states = new Map();
5
+ startTask(taskId, complexity, maxRetries = 3) {
6
+ const state = {
7
+ taskId,
8
+ currentPhase: 'plan',
9
+ iteration: 0,
10
+ maxRetries,
11
+ modelTier: getModelTier(complexity),
12
+ escalationCount: 0,
13
+ failures: [],
14
+ };
15
+ this.states.set(taskId, state);
16
+ return { ...state };
17
+ }
18
+ recordFailure(taskId, reason, failureType) {
19
+ const state = this.states.get(taskId);
20
+ if (!state) {
21
+ return { ok: false, error: 'Task not found', hint: `No PDCA state for taskId: ${taskId}` };
22
+ }
23
+ const failure = {
24
+ iteration: state.iteration,
25
+ phase: state.currentPhase,
26
+ reason,
27
+ modelUsed: state.modelTier,
28
+ timestamp: new Date().toISOString(),
29
+ };
30
+ state.failures.push(failure);
31
+ state.iteration += 1;
32
+ if (failureType === 'reasoning') {
33
+ if (this.shouldEscalateModel(state)) {
34
+ const next = this.nextModelTier(state.modelTier);
35
+ if (next === null) {
36
+ // Already at opus — no higher model available, escalate to human
37
+ state.currentPhase = 'escalated';
38
+ }
39
+ else {
40
+ state.modelTier = next;
41
+ state.escalationCount += 1;
42
+ // Reset to plan phase on model escalation
43
+ state.currentPhase = 'plan';
44
+ }
45
+ }
46
+ else if (state.iteration >= state.maxRetries && state.modelTier === 'opus') {
47
+ state.currentPhase = 'escalated';
48
+ }
49
+ }
50
+ else {
51
+ // 'prompt' or 'task_definition' or 'unknown' — no model escalation
52
+ if (state.iteration >= state.maxRetries) {
53
+ state.currentPhase = 'escalated';
54
+ }
55
+ }
56
+ return { ok: true, value: { ...state } };
57
+ }
58
+ completeTask(taskId) {
59
+ const state = this.states.get(taskId);
60
+ if (!state) {
61
+ return { ok: false, error: 'Task not found', hint: `No PDCA state for taskId: ${taskId}` };
62
+ }
63
+ state.currentPhase = 'done';
64
+ return { ok: true, value: { ...state } };
65
+ }
66
+ getState(taskId) {
67
+ const state = this.states.get(taskId);
68
+ return state ? { ...state } : undefined;
69
+ }
70
+ shouldEscalateModel(state) {
71
+ // Count reasoning failures for the current model tier
72
+ const reasoningFailuresForCurrentModel = state.failures.filter((f) => f.modelUsed === state.modelTier).length;
73
+ return reasoningFailuresForCurrentModel >= 2;
74
+ }
75
+ nextModelTier(current) {
76
+ if (current === 'haiku')
77
+ return 'sonnet';
78
+ if (current === 'sonnet')
79
+ return 'opus';
80
+ return null; // opus → needs human
81
+ }
82
+ }
83
+ //# sourceMappingURL=pdca.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pdca.js","sourceRoot":"","sources":["../../../src/pm/pdca.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { OverlayStore } from '../core/store.js';
2
+ export interface RecallResult {
3
+ id: string;
4
+ type: 'task' | 'story' | 'epic' | 'session' | 'pdca' | 'lesson';
5
+ title: string;
6
+ excerpt: string;
7
+ relevanceScore: number;
8
+ status?: string;
9
+ created_at: string;
10
+ metadata?: Record<string, unknown>;
11
+ }
12
+ export interface RecallParams {
13
+ query: string;
14
+ entityTypes?: Array<'task' | 'story' | 'epic' | 'session' | 'pdca' | 'lesson'>;
15
+ statusFilter?: string;
16
+ limit?: number;
17
+ }
18
+ export declare class RecallEngine {
19
+ private store;
20
+ constructor(store: OverlayStore);
21
+ search(params: RecallParams): RecallResult[];
22
+ private buildQueries;
23
+ }
@@ -0,0 +1,126 @@
1
+ const PER_ENTITY_LIMIT = 100;
2
+ export class RecallEngine {
3
+ store;
4
+ constructor(store) {
5
+ this.store = store;
6
+ }
7
+ search(params) {
8
+ const { query, entityTypes, statusFilter, limit = 10 } = params;
9
+ if (!query.trim())
10
+ return [];
11
+ const pattern = `%${query.replace(/%/g, '\\%').replace(/_/g, '\\_')}%`;
12
+ const now = new Date();
13
+ const types = entityTypes ?? ['task', 'story', 'epic', 'session', 'pdca', 'lesson'];
14
+ const queries = this.buildQueries(types, pattern, statusFilter);
15
+ const results = [];
16
+ for (const eq of queries) {
17
+ const rows = this.store.query(eq.sql, eq.params);
18
+ for (const row of rows) {
19
+ const r = eq.mapRow(row);
20
+ r.relevanceScore = scoreResult(query, [r.title, r.excerpt], r.created_at, now, r.status);
21
+ results.push(r);
22
+ }
23
+ }
24
+ results.sort((a, b) => b.relevanceScore - a.relevanceScore);
25
+ return results.slice(0, Math.min(limit, 50));
26
+ }
27
+ buildQueries(types, pattern, statusFilter) {
28
+ const queries = [];
29
+ const esc = `ESCAPE '\\'`;
30
+ const lim = `LIMIT ${PER_ENTITY_LIMIT}`;
31
+ if (types.includes('task')) {
32
+ const where = statusFilter
33
+ ? `(title LIKE ? ${esc} OR description LIKE ? ${esc} OR why LIKE ? ${esc} OR last_failure_reason LIKE ? ${esc}) AND status = ?`
34
+ : `(title LIKE ? ${esc} OR description LIKE ? ${esc} OR why LIKE ? ${esc} OR last_failure_reason LIKE ? ${esc})`;
35
+ const params = statusFilter ? [pattern, pattern, pattern, pattern, statusFilter] : [pattern, pattern, pattern, pattern];
36
+ queries.push({
37
+ type: 'task',
38
+ sql: `SELECT id, title, description, why, status, complexity, last_failure_reason, created_at FROM tasks WHERE ${where} ${lim}`,
39
+ params,
40
+ mapRow: (r) => ({
41
+ id: r.id, type: 'task', title: r.title,
42
+ excerpt: truncate([r.description, r.why, r.last_failure_reason].filter(Boolean).join(' — ')),
43
+ relevanceScore: 0, status: r.status, created_at: r.created_at,
44
+ metadata: { complexity: r.complexity },
45
+ }),
46
+ });
47
+ }
48
+ if (types.includes('story')) {
49
+ queries.push({
50
+ type: 'story',
51
+ sql: `SELECT id, title, user_story, why, status, created_at FROM stories WHERE title LIKE ? ${esc} OR user_story LIKE ? ${esc} OR why LIKE ? ${esc} ${lim}`,
52
+ params: [pattern, pattern, pattern],
53
+ mapRow: (r) => ({
54
+ id: r.id, type: 'story', title: r.title,
55
+ excerpt: truncate([r.user_story, r.why].filter(Boolean).join(' — ')),
56
+ relevanceScore: 0, status: r.status, created_at: r.created_at,
57
+ }),
58
+ });
59
+ }
60
+ if (types.includes('epic')) {
61
+ queries.push({
62
+ type: 'epic',
63
+ sql: `SELECT id, title, description, why, status, created_at FROM epics WHERE title LIKE ? ${esc} OR description LIKE ? ${esc} OR why LIKE ? ${esc} ${lim}`,
64
+ params: [pattern, pattern, pattern],
65
+ mapRow: (r) => ({
66
+ id: r.id, type: 'epic', title: r.title,
67
+ excerpt: truncate([r.description, r.why].filter(Boolean).join(' — ')),
68
+ relevanceScore: 0, status: r.status, created_at: r.created_at,
69
+ }),
70
+ });
71
+ }
72
+ if (types.includes('session')) {
73
+ queries.push({
74
+ type: 'session',
75
+ sql: `SELECT id, goal, status, started_at FROM sessions WHERE goal LIKE ? ${esc} ${lim}`,
76
+ params: [pattern],
77
+ mapRow: (r) => ({
78
+ id: r.id, type: 'session', title: r.goal ?? 'Session',
79
+ excerpt: truncate(r.goal ?? ''),
80
+ relevanceScore: 0, status: r.status, created_at: r.started_at,
81
+ }),
82
+ });
83
+ }
84
+ if (types.includes('pdca')) {
85
+ queries.push({
86
+ type: 'pdca',
87
+ sql: `SELECT id, task_id, iteration, phase, model_used, failure_reason, outcome, timestamp FROM pdca_iterations WHERE failure_reason LIKE ? ${esc} OR outcome LIKE ? ${esc} ${lim}`,
88
+ params: [pattern, pattern],
89
+ mapRow: (r) => ({
90
+ id: `PDCA-${r.id}`, type: 'pdca', title: `PDCA ${r.task_id} iter ${r.iteration}`,
91
+ excerpt: truncate([r.failure_reason, r.outcome].filter(Boolean).join(' — ')),
92
+ relevanceScore: 0, created_at: r.timestamp,
93
+ metadata: { task_id: r.task_id, phase: r.phase, model_used: r.model_used },
94
+ }),
95
+ });
96
+ }
97
+ if (types.includes('lesson')) {
98
+ queries.push({
99
+ type: 'lesson',
100
+ sql: `SELECT id, source, entity_id, failure_type, description, action, created_at FROM lessons_learned WHERE description LIKE ? ${esc} OR action LIKE ? ${esc} ${lim}`,
101
+ params: [pattern, pattern],
102
+ mapRow: (r) => ({
103
+ id: `LESSON-${r.id}`, type: 'lesson', title: `Lesson from ${r.source}: ${r.entity_id}`,
104
+ excerpt: truncate([r.description, r.action].filter(Boolean).join(' — ')),
105
+ relevanceScore: 0, created_at: r.created_at,
106
+ metadata: { source: r.source, failure_type: r.failure_type },
107
+ }),
108
+ });
109
+ }
110
+ return queries;
111
+ }
112
+ }
113
+ function scoreResult(query, fields, timestamp, now, status) {
114
+ const terms = query.toLowerCase().split(/\s+/).filter(t => t.length > 0);
115
+ const text = fields.filter(Boolean).join(' ').toLowerCase();
116
+ const tfScore = terms.length > 0 ? terms.filter(t => text.includes(t)).length / terms.length : 0;
117
+ const ageMs = Math.max(0, now.getTime() - new Date(timestamp).getTime());
118
+ const recencyScore = Math.exp(-ageMs / (1000 * 60 * 60 * 24 * 30));
119
+ const statusBoostMap = { in_progress: 0.3, done: 0.1 };
120
+ const statusBoost = statusBoostMap[status ?? ''] ?? 0;
121
+ return tfScore * 0.6 + recencyScore * 0.3 + statusBoost * 0.1;
122
+ }
123
+ function truncate(text, max = 200) {
124
+ return text.length > max ? text.slice(0, max) + '...' : text;
125
+ }
126
+ //# sourceMappingURL=recall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recall.js","sourceRoot":"","sources":["../../../src/pm/recall.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import type { OverlayStore } from '../core/store.js';
2
+ import type { EvmHealth } from '../core/types.js';
3
+ export interface RetroReport {
4
+ session_id: string;
5
+ goal: string;
6
+ progress: {
7
+ done: number;
8
+ total: number;
9
+ percent: number;
10
+ };
11
+ evm: {
12
+ spi: number;
13
+ cpi: number;
14
+ health: EvmHealth;
15
+ };
16
+ tokens: {
17
+ spent: number;
18
+ budget: number;
19
+ percent: number;
20
+ };
21
+ velocity: number;
22
+ lessons: Array<{
23
+ source: string;
24
+ description: string;
25
+ }>;
26
+ went_well: string[];
27
+ recommendations: string[];
28
+ }
29
+ export declare class RetrospectiveEngine {
30
+ private store;
31
+ constructor(store: OverlayStore);
32
+ generate(sessionId?: string): RetroReport | null;
33
+ formatMarkdown(report: RetroReport): string;
34
+ private loadCalibration;
35
+ }
@@ -0,0 +1,104 @@
1
+ import { EvmEngine } from './evm.js';
2
+ import { CalibrationEngine } from './calibration.js';
3
+ export class RetrospectiveEngine {
4
+ store;
5
+ constructor(store) {
6
+ this.store = store;
7
+ }
8
+ generate(sessionId) {
9
+ // Find session
10
+ const session = sessionId
11
+ ? this.store.query('SELECT id, goal, token_budget, tokens_spent, velocity_points FROM sessions WHERE id = ?', [sessionId])[0]
12
+ : this.store.query('SELECT id, goal, token_budget, tokens_spent, velocity_points FROM sessions ORDER BY started_at DESC LIMIT 1')[0];
13
+ if (!session)
14
+ return null;
15
+ // Get session tasks
16
+ const taskIds = this.store.query('SELECT task_id FROM session_tasks WHERE session_id = ?', [session.id]);
17
+ const tasks = taskIds.length > 0
18
+ ? this.store.query(`SELECT id, status, complexity, model_tier FROM tasks WHERE id IN (${taskIds.map(() => '?').join(',')})`, taskIds.map(t => t.task_id))
19
+ : [];
20
+ const done = tasks.filter(t => t.status === 'done').length;
21
+ const total = tasks.length;
22
+ // EVM metrics
23
+ const calibration = this.loadCalibration();
24
+ const evm = new EvmEngine(calibration);
25
+ const evmTasks = tasks.map(t => {
26
+ const metrics = this.store.query('SELECT planned_tokens, actual_tokens FROM evm_metrics WHERE task_id = ?', [t.id])[0];
27
+ return {
28
+ taskId: t.id, complexity: t.complexity,
29
+ plannedTokens: metrics?.planned_tokens ?? calibration.getEstimate(t.complexity),
30
+ actualTokens: metrics?.actual_tokens ?? 0, status: t.status,
31
+ };
32
+ });
33
+ const evmMetrics = evm.calculateMetrics(evmTasks);
34
+ // Lessons from this session's tasks
35
+ const lessons = tasks.length > 0
36
+ ? this.store.query(`SELECT source, description FROM lessons_learned WHERE entity_id IN (${tasks.map(() => '?').join(',')}) ORDER BY created_at DESC LIMIT 50`, tasks.map(t => t.id))
37
+ : [];
38
+ // What went well
39
+ const wentWell = [];
40
+ if (done > 0)
41
+ wentWell.push(`${done} task${done > 1 ? 's' : ''} completed`);
42
+ if (evmMetrics.cpi >= 1.0)
43
+ wentWell.push('Under budget (CPI >= 1.0)');
44
+ if (evmMetrics.spi >= 1.0)
45
+ wentWell.push('On schedule (SPI >= 1.0)');
46
+ const escalatedCount = tasks.filter(t => t.status === 'blocked').length;
47
+ if (escalatedCount === 0 && total > 0)
48
+ wentWell.push('No escalations needed');
49
+ // Recommendations
50
+ const recommendations = [];
51
+ if (evmMetrics.cpi < 0.85)
52
+ recommendations.push('CPI below 0.85 — review token estimates for high-complexity tasks');
53
+ if (evmMetrics.spi < 0.85)
54
+ recommendations.push('SPI below 0.85 — consider reducing scope or splitting tasks');
55
+ if (escalatedCount > 0)
56
+ recommendations.push(`${escalatedCount} task(s) blocked — review escalation patterns`);
57
+ const highComplexity = tasks.filter(t => t.complexity >= 7).length;
58
+ if (highComplexity > 2)
59
+ recommendations.push(`${highComplexity} high-complexity tasks — consider decomposition`);
60
+ if (recommendations.length === 0)
61
+ recommendations.push('Session healthy — continue current approach');
62
+ const budget = session.token_budget ?? 0;
63
+ const spent = session.tokens_spent ?? 0;
64
+ return {
65
+ session_id: session.id,
66
+ goal: session.goal ?? 'No goal set',
67
+ progress: { done, total, percent: total === 0 ? 0 : Math.round((done / total) * 100) },
68
+ evm: { spi: Math.round(evmMetrics.spi * 100) / 100, cpi: Math.round(evmMetrics.cpi * 100) / 100, health: evmMetrics.health },
69
+ tokens: { spent, budget, percent: budget === 0 ? 0 : Math.round((spent / budget) * 100) },
70
+ velocity: session.velocity_points ?? 0,
71
+ lessons,
72
+ went_well: wentWell,
73
+ recommendations,
74
+ };
75
+ }
76
+ formatMarkdown(report) {
77
+ const lines = [
78
+ `## Retrospective: ${report.goal}`,
79
+ `### Progress: ${report.progress.done}/${report.progress.total} tasks (${report.progress.percent}%)`,
80
+ `### EVM: SPI ${report.evm.spi} | CPI ${report.evm.cpi} | Health: ${report.evm.health}`,
81
+ `### Token Budget: ${report.tokens.spent}/${report.tokens.budget} (${report.tokens.percent}% used)`,
82
+ `### Velocity: ${report.velocity} points`,
83
+ ];
84
+ if (report.went_well.length > 0) {
85
+ lines.push('### What Went Well:');
86
+ for (const item of report.went_well)
87
+ lines.push(` - ${item}`);
88
+ }
89
+ if (report.lessons.length > 0) {
90
+ lines.push('### Lessons Learned:');
91
+ for (const l of report.lessons)
92
+ lines.push(` - [${l.source}] ${l.description}`);
93
+ }
94
+ lines.push('### Recommendations:');
95
+ for (const r of report.recommendations)
96
+ lines.push(` - ${r}`);
97
+ return lines.join('\n');
98
+ }
99
+ loadCalibration() {
100
+ const rows = this.store.query('SELECT complexity_score, avg_tokens, sample_count FROM calibration ORDER BY complexity_score');
101
+ return new CalibrationEngine(rows.length > 0 ? rows : undefined);
102
+ }
103
+ }
104
+ //# sourceMappingURL=retrospective.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retrospective.js","sourceRoot":"","sources":["../../../src/pm/retrospective.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ export interface Session {
2
+ id: string;
3
+ goal: string;
4
+ tokenBudget: number;
5
+ tokensSpent: number;
6
+ taskIds: string[];
7
+ status: 'active' | 'completed';
8
+ startedAt: string;
9
+ completedAt?: string;
10
+ velocityPoints: number;
11
+ }
12
+ export interface SessionSummary {
13
+ id: string;
14
+ goal: string;
15
+ tasksCompleted: number;
16
+ tasksTotal: number;
17
+ tokensSpent: number;
18
+ tokenBudget: number;
19
+ tokensRemaining: number;
20
+ velocityPoints: number;
21
+ percentComplete: number;
22
+ }
23
+ export declare class SessionManager {
24
+ private currentSession;
25
+ private sessionCounter;
26
+ private completedTasks;
27
+ startSession(goal: string, tokenBudget: number): Session;
28
+ getCurrentSession(): Session | null;
29
+ addTask(taskId: string): void;
30
+ recordTokens(_taskId: string, tokens: number): void;
31
+ recordTaskCompletion(taskId: string, complexity: number): void;
32
+ getSummary(): SessionSummary | null;
33
+ endSession(): SessionSummary;
34
+ isOverBudget(): boolean;
35
+ autoStart(goal: string, defaultBudget: number): Session;
36
+ }
@@ -0,0 +1,91 @@
1
+ export class SessionManager {
2
+ currentSession = null;
3
+ sessionCounter = 0;
4
+ completedTasks = new Set();
5
+ startSession(goal, tokenBudget) {
6
+ this.sessionCounter += 1;
7
+ const id = `SESSION-${String(this.sessionCounter).padStart(3, '0')}`;
8
+ this.currentSession = {
9
+ id,
10
+ goal,
11
+ tokenBudget,
12
+ tokensSpent: 0,
13
+ taskIds: [],
14
+ status: 'active',
15
+ startedAt: new Date().toISOString(),
16
+ velocityPoints: 0,
17
+ };
18
+ this.completedTasks = new Set();
19
+ return { ...this.currentSession };
20
+ }
21
+ getCurrentSession() {
22
+ return this.currentSession ? { ...this.currentSession } : null;
23
+ }
24
+ addTask(taskId) {
25
+ if (!this.currentSession || this.currentSession.status !== 'active') {
26
+ throw new Error('No active session. Call startSession first.');
27
+ }
28
+ if (!this.currentSession.taskIds.includes(taskId)) {
29
+ this.currentSession.taskIds.push(taskId);
30
+ }
31
+ }
32
+ recordTokens(_taskId, tokens) {
33
+ if (!this.currentSession) {
34
+ throw new Error('No active session.');
35
+ }
36
+ this.currentSession.tokensSpent += tokens;
37
+ }
38
+ recordTaskCompletion(taskId, complexity) {
39
+ if (!this.currentSession) {
40
+ throw new Error('No active session.');
41
+ }
42
+ if (!this.completedTasks.has(taskId)) {
43
+ this.completedTasks.add(taskId);
44
+ this.currentSession.velocityPoints += complexity;
45
+ }
46
+ }
47
+ getSummary() {
48
+ if (!this.currentSession)
49
+ return null;
50
+ const s = this.currentSession;
51
+ const tasksTotal = s.taskIds.length;
52
+ const tasksCompleted = this.completedTasks.size;
53
+ const percentComplete = tasksTotal === 0 ? 0 : (tasksCompleted / tasksTotal) * 100;
54
+ return {
55
+ id: s.id,
56
+ goal: s.goal,
57
+ tasksCompleted,
58
+ tasksTotal,
59
+ tokensSpent: s.tokensSpent,
60
+ tokenBudget: s.tokenBudget,
61
+ tokensRemaining: s.tokenBudget - s.tokensSpent,
62
+ velocityPoints: s.velocityPoints,
63
+ percentComplete,
64
+ };
65
+ }
66
+ endSession() {
67
+ if (!this.currentSession) {
68
+ throw new Error('No active session to end.');
69
+ }
70
+ this.currentSession.status = 'completed';
71
+ this.currentSession.completedAt = new Date().toISOString();
72
+ const summary = this.getSummary();
73
+ if (!summary) {
74
+ throw new Error('Failed to generate summary.');
75
+ }
76
+ this.currentSession = null;
77
+ return summary;
78
+ }
79
+ isOverBudget() {
80
+ if (!this.currentSession)
81
+ return false;
82
+ return this.currentSession.tokensSpent > this.currentSession.tokenBudget;
83
+ }
84
+ autoStart(goal, defaultBudget) {
85
+ if (!this.currentSession || this.currentSession.status !== 'active') {
86
+ return this.startSession(goal, defaultBudget);
87
+ }
88
+ return { ...this.currentSession };
89
+ }
90
+ }
91
+ //# sourceMappingURL=sessions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../../src/pm/sessions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { TolerancePreset, ToleranceStatus } from '../core/types.js';
2
+ export interface ToleranceConfig {
3
+ dimension: string;
4
+ target: number;
5
+ upperBound: number;
6
+ unit: string;
7
+ }
8
+ export interface ToleranceCheckResult {
9
+ dimension: string;
10
+ actual: number;
11
+ target: number;
12
+ upperBound: number;
13
+ status: ToleranceStatus;
14
+ percentUsed: number;
15
+ }
16
+ export declare const TOLERANCE_PRESETS: Record<TolerancePreset, ToleranceConfig[]>;
17
+ export declare class ToleranceChecker {
18
+ check(planned: number, actual: number, config: ToleranceConfig): ToleranceCheckResult;
19
+ getPreset(preset: TolerancePreset): ToleranceConfig[];
20
+ checkTask(plannedTokens: number, actualTokens: number, preset: TolerancePreset): ToleranceCheckResult[];
21
+ }
@@ -0,0 +1,54 @@
1
+ // Presets based on PM best practices (PRINCE2 Manage by Exception)
2
+ export const TOLERANCE_PRESETS = {
3
+ 'new-feature': [
4
+ { dimension: 'cost', target: 1.0, upperBound: 1.2, unit: 'ratio' }, // ±20%
5
+ { dimension: 'token_headroom', target: 1.0, upperBound: 1.25, unit: 'ratio' }, // ±25%
6
+ ],
7
+ 'bug-fix': [
8
+ { dimension: 'cost', target: 1.0, upperBound: 1.05, unit: 'ratio' }, // ±5%
9
+ { dimension: 'token_headroom', target: 1.0, upperBound: 1.1, unit: 'ratio' }, // ±10%
10
+ ],
11
+ 'refactor': [
12
+ { dimension: 'cost', target: 1.0, upperBound: 1.1, unit: 'ratio' }, // ±10%
13
+ { dimension: 'token_headroom', target: 1.0, upperBound: 1.3, unit: 'ratio' }, // ±30%
14
+ ],
15
+ 'spike': [
16
+ { dimension: 'cost', target: 1.0, upperBound: 1.5, unit: 'ratio' }, // ±50%
17
+ { dimension: 'token_headroom', target: 1.0, upperBound: 2.0, unit: 'ratio' }, // ±100%
18
+ ],
19
+ };
20
+ export class ToleranceChecker {
21
+ check(planned, actual, config) {
22
+ // Calculate ratio = actual / planned
23
+ const ratio = planned === 0 ? 1.0 : actual / planned;
24
+ // percentUsed = ratio / upperBound as percentage
25
+ const percentUsed = config.upperBound === 0 ? 100 : (ratio / config.upperBound) * 100;
26
+ // at_risk: > 90% of upper bound; breached: > upper bound
27
+ let status;
28
+ if (ratio > config.upperBound) {
29
+ status = 'breached';
30
+ }
31
+ else if (ratio > config.upperBound * 0.9) {
32
+ status = 'at_risk';
33
+ }
34
+ else {
35
+ status = 'on_track';
36
+ }
37
+ return {
38
+ dimension: config.dimension,
39
+ actual: ratio,
40
+ target: config.target,
41
+ upperBound: config.upperBound,
42
+ status,
43
+ percentUsed,
44
+ };
45
+ }
46
+ getPreset(preset) {
47
+ return TOLERANCE_PRESETS[preset];
48
+ }
49
+ checkTask(plannedTokens, actualTokens, preset) {
50
+ const configs = this.getPreset(preset);
51
+ return configs.map((config) => this.check(plannedTokens, actualTokens, config));
52
+ }
53
+ }
54
+ //# sourceMappingURL=tolerances.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tolerances.js","sourceRoot":"","sources":["../../../src/pm/tolerances.ts"],"names":[],"mappings":"AAkBA,mEAAmE;AACnE,MAAM,CAAC,MAAM,iBAAiB,GAA+C;IAC3E,aAAa,EAAE;QACb,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,EAAG,OAAO;QAC5E,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,OAAO;KACvF;IACD,SAAS,EAAE;QACT,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,EAAG,MAAM;QAC5E,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,EAAI,OAAO;KACxF;IACD,UAAU,EAAE;QACV,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,EAAI,OAAO;QAC7E,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,EAAI,OAAO;KACxF;IACD,OAAO,EAAE;QACP,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,EAAI,OAAO;QAC7E,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,EAAI,QAAQ;KACzF;CACF,CAAC;AAEF,MAAM,OAAO,gBAAgB;IAC3B,KAAK,CAAC,OAAe,EAAE,MAAc,EAAE,MAAuB;QAC5D,qCAAqC;QACrC,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,GAAG,OAAO,CAAC;QAErD,iDAAiD;QACjD,MAAM,WAAW,GAAG,MAAM,CAAC,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC;QAEtF,yDAAyD;QACzD,IAAI,MAAuB,CAAC;QAC5B,IAAI,KAAK,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;YAC9B,MAAM,GAAG,UAAU,CAAC;QACtB,CAAC;aAAM,IAAI,KAAK,GAAG,MAAM,CAAC,UAAU,GAAG,GAAG,EAAE,CAAC;YAC3C,MAAM,GAAG,SAAS,CAAC;QACrB,CAAC;aAAM,CAAC;YACN,MAAM,GAAG,UAAU,CAAC;QACtB,CAAC;QAED,OAAO;YACL,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,MAAM,EAAE,KAAK;YACb,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,MAAM;YACN,WAAW;SACZ,CAAC;IACJ,CAAC;IAED,SAAS,CAAC,MAAuB;QAC/B,OAAO,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC;IAED,SAAS,CACP,aAAqB,EACrB,YAAoB,EACpB,MAAuB;QAEvB,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACvC,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC;IAClF,CAAC;CACF"}