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.
- package/dist/bin/forgepm.d.ts +2 -0
- package/dist/bin/forgepm.js +4 -0
- package/dist/bin/forgepm.js.map +1 -0
- package/dist/src/backends/base.d.ts +23 -0
- package/dist/src/backends/base.js +2 -0
- package/dist/src/backends/base.js.map +1 -0
- package/dist/src/backends/http-utils.d.ts +6 -0
- package/dist/src/backends/http-utils.js +36 -0
- package/dist/src/backends/http-utils.js.map +1 -0
- package/dist/src/backends/jira.d.ts +16 -0
- package/dist/src/backends/jira.js +117 -0
- package/dist/src/backends/jira.js.map +1 -0
- package/dist/src/backends/linear.d.ts +11 -0
- package/dist/src/backends/linear.js +85 -0
- package/dist/src/backends/linear.js.map +1 -0
- package/dist/src/cli/archaeology.d.ts +38 -0
- package/dist/src/cli/archaeology.js +182 -0
- package/dist/src/cli/archaeology.js.map +1 -0
- package/dist/src/cli/index.d.ts +1 -0
- package/dist/src/cli/index.js +351 -0
- package/dist/src/cli/index.js.map +1 -0
- package/dist/src/core/event-bus.d.ts +17 -0
- package/dist/src/core/event-bus.js +33 -0
- package/dist/src/core/event-bus.js.map +1 -0
- package/dist/src/core/event-plugins.d.ts +6 -0
- package/dist/src/core/event-plugins.js +2 -0
- package/dist/src/core/event-plugins.js.map +1 -0
- package/dist/src/core/forge-ops.d.ts +42 -0
- package/dist/src/core/forge-ops.js +101 -0
- package/dist/src/core/forge-ops.js.map +1 -0
- package/dist/src/core/forge.d.ts +44 -0
- package/dist/src/core/forge.js +86 -0
- package/dist/src/core/forge.js.map +1 -0
- package/dist/src/core/schema.d.ts +8 -0
- package/dist/src/core/schema.js +139 -0
- package/dist/src/core/schema.js.map +1 -0
- package/dist/src/core/store.d.ts +24 -0
- package/dist/src/core/store.js +155 -0
- package/dist/src/core/store.js.map +1 -0
- package/dist/src/core/types.d.ts +91 -0
- package/dist/src/core/types.js +19 -0
- package/dist/src/core/types.js.map +1 -0
- package/dist/src/core/version.d.ts +1 -0
- package/dist/src/core/version.js +20 -0
- package/dist/src/core/version.js.map +1 -0
- package/dist/src/github/pull.d.ts +13 -0
- package/dist/src/github/pull.js +51 -0
- package/dist/src/github/pull.js.map +1 -0
- package/dist/src/github/push.d.ts +20 -0
- package/dist/src/github/push.js +118 -0
- package/dist/src/github/push.js.map +1 -0
- package/dist/src/github/setup.d.ts +10 -0
- package/dist/src/github/setup.js +112 -0
- package/dist/src/github/setup.js.map +1 -0
- package/dist/src/github/slack.d.ts +12 -0
- package/dist/src/github/slack.js +33 -0
- package/dist/src/github/slack.js.map +1 -0
- package/dist/src/index.d.ts +14 -0
- package/dist/src/index.js +9 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/mcp/server.d.ts +5 -0
- package/dist/src/mcp/server.js +69 -0
- package/dist/src/mcp/server.js.map +1 -0
- package/dist/src/mcp/tool-handlers.d.ts +19 -0
- package/dist/src/mcp/tool-handlers.js +123 -0
- package/dist/src/mcp/tool-handlers.js.map +1 -0
- package/dist/src/pm/calibration.d.ts +13 -0
- package/dist/src/pm/calibration.js +56 -0
- package/dist/src/pm/calibration.js.map +1 -0
- package/dist/src/pm/callsheet.d.ts +66 -0
- package/dist/src/pm/callsheet.js +91 -0
- package/dist/src/pm/callsheet.js.map +1 -0
- package/dist/src/pm/drift-detector.d.ts +38 -0
- package/dist/src/pm/drift-detector.js +111 -0
- package/dist/src/pm/drift-detector.js.map +1 -0
- package/dist/src/pm/evm.d.ts +31 -0
- package/dist/src/pm/evm.js +58 -0
- package/dist/src/pm/evm.js.map +1 -0
- package/dist/src/pm/pdca.d.ts +27 -0
- package/dist/src/pm/pdca.js +83 -0
- package/dist/src/pm/pdca.js.map +1 -0
- package/dist/src/pm/recall.d.ts +23 -0
- package/dist/src/pm/recall.js +126 -0
- package/dist/src/pm/recall.js.map +1 -0
- package/dist/src/pm/retrospective.d.ts +35 -0
- package/dist/src/pm/retrospective.js +104 -0
- package/dist/src/pm/retrospective.js.map +1 -0
- package/dist/src/pm/sessions.d.ts +36 -0
- package/dist/src/pm/sessions.js +91 -0
- package/dist/src/pm/sessions.js.map +1 -0
- package/dist/src/pm/tolerances.d.ts +21 -0
- package/dist/src/pm/tolerances.js +54 -0
- package/dist/src/pm/tolerances.js.map +1 -0
- package/dist/src/utils/validation.d.ts +2 -0
- package/dist/src/utils/validation.js +8 -0
- package/dist/src/utils/validation.js.map +1 -0
- 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"}
|