pi-harness-runtime 0.10.4 → 0.10.6
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/index.ts +24 -0
- package/package.json +1 -1
- package/packages/a2a-adapter/package.json +1 -1
- package/packages/auth/package.json +1 -1
- package/packages/autonomous-refactor/package.json +1 -1
- package/packages/autonomous-runtime/package.json +1 -1
- package/packages/cache-strategy/package.json +1 -1
- package/packages/capability-registry/package.json +1 -1
- package/packages/checkpoint/package.json +1 -1
- package/packages/cli-plugin-sdk/package.json +1 -1
- package/packages/clipboard/package.json +1 -1
- package/packages/code-generation/package.json +1 -1
- package/packages/code-review/package.json +1 -1
- package/packages/codex-adapter/package.json +1 -1
- package/packages/config-capture/package.json +23 -0
- package/packages/config-capture/src/index.ts +357 -0
- package/packages/context-compiler/package.json +1 -1
- package/packages/context-discovery/package.json +1 -1
- package/packages/context-manager/package.json +1 -1
- package/packages/cookie-sanitizer/package.json +1 -1
- package/packages/cost-optimizer/package.json +1 -1
- package/packages/dependency-analyzer/package.json +1 -1
- package/packages/django-plugin/package.json +1 -1
- package/packages/doc-generator/package.json +1 -1
- package/packages/evaluation-engine/package.json +1 -1
- package/packages/evaluation-runner/package.json +1 -1
- package/packages/event-bus/package.json +1 -1
- package/packages/event-store/package.json +1 -1
- package/packages/experience-replay/package.json +1 -1
- package/packages/feedback-collector/package.json +1 -1
- package/packages/framework-detector/package.json +1 -1
- package/packages/framework-plugin-sdk/package.json +1 -1
- package/packages/frappe-plugin/package.json +1 -1
- package/packages/generic-web-plugin/package.json +1 -1
- package/packages/health-monitor/package.json +1 -1
- package/packages/intent-analyzer/package.json +1 -1
- package/packages/laravel-plugin/package.json +1 -1
- package/packages/learning-engine/package.json +1 -1
- package/packages/mcp-adapter/package.json +1 -1
- package/packages/memory-engine/package.json +1 -1
- package/packages/model-registry/package.json +1 -1
- package/packages/nextjs-plugin/package.json +1 -1
- package/packages/notification/package.json +1 -1
- package/packages/observability/package.json +1 -1
- package/packages/performance-optimizer/package.json +1 -1
- package/packages/privilege-broker/package.json +1 -1
- package/packages/project-analyzer/package.json +1 -1
- package/packages/projection-engine/package.json +1 -1
- package/packages/prompt-compiler/package.json +1 -1
- package/packages/prompt-versioning/package.json +1 -1
- package/packages/provider-adapter-sdk/package.json +1 -1
- package/packages/provider-router/package.json +1 -1
- package/packages/provider-selector/package.json +1 -1
- package/packages/providers/package.json +1 -1
- package/packages/quota-manager/package.json +1 -1
- package/packages/rate-limiter/package.json +1 -1
- package/packages/react-vite-plugin/package.json +1 -1
- package/packages/release-manager/package.json +1 -1
- package/packages/requirement-compiler/package.json +1 -1
- package/packages/runtime/package.json +1 -1
- package/packages/scheduler/package.json +1 -1
- package/packages/scheduler-adapter/package.json +1 -1
- package/packages/session/package.json +1 -1
- package/packages/session-api/package.json +1 -1
- package/packages/session-export/package.json +1 -1
- package/packages/shared-context/package.json +1 -1
- package/packages/skill-registry/package.json +1 -1
- package/packages/sprint-planner/package.json +1 -1
- package/packages/subscription-engine/package.json +1 -1
- package/packages/task-compiler/package.json +1 -1
- package/packages/test-data-generator/package.json +1 -1
- package/packages/test-generator/package.json +1 -1
- package/packages/todo-bd-sync/package.json +1 -1
- package/packages/todo-bd-sync/src/extension.ts +47 -71
- package/packages/todo-bd-sync/src/task-analyzer.ts +266 -0
- package/packages/token-estimation/package.json +1 -1
- package/packages/token-optimizer/package.json +1 -1
- package/packages/tui/package.json +1 -1
- package/packages/types/package.json +1 -1
- package/packages/workflow-events/package.json +1 -1
- package/packages/workspace-scanner/package.json +1 -1
- package/packages/worktree/package.json +1 -1
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Smart Auto-Todo Task Analyzer
|
|
3
|
+
*
|
|
4
|
+
* Decides when to automatically create bd issues based on:
|
|
5
|
+
* 1. Task complexity signals
|
|
6
|
+
* 2. Session state (pending task count)
|
|
7
|
+
*
|
|
8
|
+
* Philosophy:
|
|
9
|
+
* - Simple tasks (grep, quick edit) -> NO todo (avoid noise)
|
|
10
|
+
* - Complex tasks OR multiple pending tasks -> AUTO-CREATE todo
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { getOpenBdIssues } from "./sync.js";
|
|
14
|
+
|
|
15
|
+
// ─── Complexity Signals ─────────────────────────────────────────────────────────
|
|
16
|
+
|
|
17
|
+
interface TaskSignals {
|
|
18
|
+
/** Estimated number of steps required */
|
|
19
|
+
stepCount: number;
|
|
20
|
+
/** Number of files likely involved */
|
|
21
|
+
fileCount: number;
|
|
22
|
+
/** Requires research (web search, docs lookup) */
|
|
23
|
+
needsResearch: boolean;
|
|
24
|
+
/** Creates new files */
|
|
25
|
+
createsFiles: boolean;
|
|
26
|
+
/** User explicitly says task is complex */
|
|
27
|
+
explicitlyComplex: boolean;
|
|
28
|
+
/** Likely to have subtasks discovered during work */
|
|
29
|
+
likelySubtasks: boolean;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const COMPLEX_KEYWORDS = [
|
|
33
|
+
"complicated", "complex", "tricky", "difficult", "refactor",
|
|
34
|
+
"architecture", "design", "implement from scratch", "rewrite",
|
|
35
|
+
"investigate", "debug", "fix the bug", "performance",
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
const RESEARCH_KEYWORDS = [
|
|
39
|
+
"search", "look up", "find", "research", "check", "verify",
|
|
40
|
+
"how to", "best practice", "compare", "evaluate", "review",
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
const SUBTASK_KEYWORDS = [
|
|
44
|
+
"also", "plus", "and also", "while you're at it", "on top of that",
|
|
45
|
+
"additionally", "another thing", "don't forget", "should also",
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Analyze user request text for complexity signals
|
|
50
|
+
*/
|
|
51
|
+
export function analyzeTaskSignals(userMessage: string): TaskSignals {
|
|
52
|
+
const lower = userMessage.toLowerCase();
|
|
53
|
+
|
|
54
|
+
// Count implied steps from action verbs
|
|
55
|
+
const actionVerbs = [
|
|
56
|
+
"create", "build", "implement", "design", "setup", "configure",
|
|
57
|
+
"migrate", "convert", "refactor", "optimize", "fix", "update",
|
|
58
|
+
"add", "remove", "delete", "modify", "change", "replace",
|
|
59
|
+
];
|
|
60
|
+
const stepCount = Math.max(1, actionVerbs.filter(v => lower.includes(v)).length);
|
|
61
|
+
|
|
62
|
+
// Estimate file count from file paths and extensions
|
|
63
|
+
const filePatterns = /[\w-]+\.(ts|js|py|json|md|yaml|yml|tsx|jsx|html|css|sql)/g;
|
|
64
|
+
const fileMatches = userMessage.match(filePatterns) || [];
|
|
65
|
+
const explicitFiles = fileMatches.length;
|
|
66
|
+
|
|
67
|
+
// Check for directory patterns
|
|
68
|
+
const dirPatterns = /(?:src|lib|packages|apps|components|hooks|utils|api)\/[\w/-]+/g;
|
|
69
|
+
const dirMatches = userMessage.match(dirPatterns) || [];
|
|
70
|
+
|
|
71
|
+
// Count "and", "also", "+" for multi-task indicators
|
|
72
|
+
const multiTaskIndicator = (lower.match(/and also|also|\+/g) || []).length;
|
|
73
|
+
const estimatedFiles = Math.max(1, explicitFiles + dirMatches.length + multiTaskIndicator);
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
stepCount,
|
|
77
|
+
fileCount: estimatedFiles,
|
|
78
|
+
needsResearch: RESEARCH_KEYWORDS.some(k => lower.includes(k)),
|
|
79
|
+
createsFiles: lower.includes("create") || lower.includes("add") || lower.includes("new"),
|
|
80
|
+
explicitlyComplex: COMPLEX_KEYWORDS.some(k => lower.includes(k)),
|
|
81
|
+
likelySubtasks: SUBTASK_KEYWORDS.some(k => lower.includes(k)) || multiTaskIndicator >= 2,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// ─── Decision Logic ───────────────────────────────────────────────────────────
|
|
86
|
+
|
|
87
|
+
export interface AutoTodoDecision {
|
|
88
|
+
shouldCreate: boolean;
|
|
89
|
+
reason: string;
|
|
90
|
+
confidence: "high" | "medium" | "low";
|
|
91
|
+
skipReason?: string;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Decide whether to auto-create a todo for the given task
|
|
96
|
+
*/
|
|
97
|
+
export function decideAutoTodo(
|
|
98
|
+
userMessage: string,
|
|
99
|
+
options: {
|
|
100
|
+
forceMode?: boolean;
|
|
101
|
+
skipMode?: boolean;
|
|
102
|
+
} = {},
|
|
103
|
+
): AutoTodoDecision {
|
|
104
|
+
const signals = analyzeTaskSignals(userMessage);
|
|
105
|
+
const pendingTasks = getOpenBdIssues().filter(i => i.status !== "closed");
|
|
106
|
+
const pendingCount = pendingTasks.length;
|
|
107
|
+
|
|
108
|
+
// ── Skip Conditions ────────────────────────────────────────────────────
|
|
109
|
+
// Never create todos for these
|
|
110
|
+
|
|
111
|
+
const simplePatterns = [
|
|
112
|
+
/^simply\s/i,
|
|
113
|
+
/^just\s/i,
|
|
114
|
+
/^quick\s/i,
|
|
115
|
+
/^can you\s+(grep|find|cat|ls|echo)/i,
|
|
116
|
+
/^(grep|find|cat|ls)\s+[\w.-]+/i,
|
|
117
|
+
/^what('s| is) the\s+\w+\s+\?$/i,
|
|
118
|
+
/^how do i\s+\w+\s*\?$/i,
|
|
119
|
+
];
|
|
120
|
+
|
|
121
|
+
if (simplePatterns.some(p => p.test(userMessage.trim()))) {
|
|
122
|
+
return {
|
|
123
|
+
shouldCreate: false,
|
|
124
|
+
reason: "Simple request (lookup/one-liner)",
|
|
125
|
+
confidence: "high",
|
|
126
|
+
skipReason: "Task is too simple to warrant tracking",
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Check for single file, single action with no complexity
|
|
131
|
+
if (
|
|
132
|
+
signals.stepCount === 1 &&
|
|
133
|
+
signals.fileCount <= 1 &&
|
|
134
|
+
!signals.needsResearch &&
|
|
135
|
+
!signals.createsFiles &&
|
|
136
|
+
!signals.explicitlyComplex &&
|
|
137
|
+
pendingCount === 0
|
|
138
|
+
) {
|
|
139
|
+
return {
|
|
140
|
+
shouldCreate: false,
|
|
141
|
+
reason: "Single action, single file, no research needed",
|
|
142
|
+
confidence: "high",
|
|
143
|
+
skipReason: "Task is straightforward",
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// ── Force Modes ──────────────────────────────────────────────────────
|
|
148
|
+
if (options.forceMode) {
|
|
149
|
+
return {
|
|
150
|
+
shouldCreate: true,
|
|
151
|
+
reason: "Force mode enabled",
|
|
152
|
+
confidence: "high",
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (options.skipMode) {
|
|
157
|
+
return {
|
|
158
|
+
shouldCreate: false,
|
|
159
|
+
reason: "Skip mode enabled",
|
|
160
|
+
confidence: "high",
|
|
161
|
+
skipReason: "User requested skip",
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// ── Auto-Create Conditions ──────────────────────────────────────────
|
|
166
|
+
const reasons: string[] = [];
|
|
167
|
+
|
|
168
|
+
// HIGH CONFIDENCE: Task explicitly complex
|
|
169
|
+
if (signals.explicitlyComplex) {
|
|
170
|
+
reasons.push("explicitly complex");
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// HIGH CONFIDENCE: Multiple steps
|
|
174
|
+
if (signals.stepCount >= 3) {
|
|
175
|
+
reasons.push(`${signals.stepCount} steps implied`);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// HIGH CONFIDENCE: Multiple files
|
|
179
|
+
if (signals.fileCount >= 3) {
|
|
180
|
+
reasons.push(`${signals.fileCount} files involved`);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// MEDIUM CONFIDENCE: Research needed
|
|
184
|
+
if (signals.needsResearch && signals.stepCount >= 2) {
|
|
185
|
+
reasons.push("research + action");
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// MEDIUM CONFIDENCE: Creates files + action
|
|
189
|
+
if (signals.createsFiles && signals.fileCount >= 2) {
|
|
190
|
+
reasons.push("creates multiple files");
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// MEDIUM CONFIDENCE: Likely subtasks
|
|
194
|
+
if (signals.likelySubtasks) {
|
|
195
|
+
reasons.push("likely has subtasks");
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// HIGH CONFIDENCE: Already 2+ pending tasks (session overload)
|
|
199
|
+
if (pendingCount >= 2) {
|
|
200
|
+
reasons.push(`${pendingCount} pending tasks in session`);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// HIGH CONFIDENCE: 3+ pending tasks
|
|
204
|
+
if (pendingCount >= 3) {
|
|
205
|
+
reasons.push("session overwhelmed (3+ pending)");
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (reasons.length === 0) {
|
|
209
|
+
return {
|
|
210
|
+
shouldCreate: false,
|
|
211
|
+
reason: "No strong complexity signals",
|
|
212
|
+
confidence: "low",
|
|
213
|
+
skipReason: "Task doesn't meet auto-create threshold",
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Need at least 2 signals OR high-pending count
|
|
218
|
+
const highConfidenceReasons = ["explicitly complex", "pending tasks in session", "session overwhelmed"];
|
|
219
|
+
const hasHighConfidence = reasons.some(r => highConfidenceReasons.some(h => r.includes(h)));
|
|
220
|
+
const shouldCreate = reasons.length >= 2 || hasHighConfidence || pendingCount >= 2;
|
|
221
|
+
|
|
222
|
+
return {
|
|
223
|
+
shouldCreate,
|
|
224
|
+
reason: reasons.join(", "),
|
|
225
|
+
confidence: hasHighConfidence ? "high" : reasons.length >= 2 ? "medium" : "low",
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// ─── Quick Score ─────────────────────────────────────────────────────────────
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Quick numeric score (0-100) for task complexity
|
|
233
|
+
* Higher = more likely to need a todo
|
|
234
|
+
*/
|
|
235
|
+
export function getTaskComplexityScore(userMessage: string): number {
|
|
236
|
+
const signals = analyzeTaskSignals(userMessage);
|
|
237
|
+
const pendingTasks = getOpenBdIssues().filter(i => i.status !== "closed");
|
|
238
|
+
|
|
239
|
+
let score = 0;
|
|
240
|
+
|
|
241
|
+
// Step count (0-25)
|
|
242
|
+
score += Math.min(25, signals.stepCount * 8);
|
|
243
|
+
|
|
244
|
+
// File count (0-20)
|
|
245
|
+
score += Math.min(20, signals.fileCount * 5);
|
|
246
|
+
|
|
247
|
+
// Research needed (0-15)
|
|
248
|
+
if (signals.needsResearch) score += 15;
|
|
249
|
+
|
|
250
|
+
// Creates files (0-10)
|
|
251
|
+
if (signals.createsFiles) score += 10;
|
|
252
|
+
|
|
253
|
+
// Explicitly complex (0-20)
|
|
254
|
+
if (signals.explicitlyComplex) score += 20;
|
|
255
|
+
|
|
256
|
+
// Likely subtasks (0-10)
|
|
257
|
+
if (signals.likelySubtasks) score += 10;
|
|
258
|
+
|
|
259
|
+
// Pending task overload (0-25)
|
|
260
|
+
const pendingCount = pendingTasks.length;
|
|
261
|
+
if (pendingCount >= 3) score += 25;
|
|
262
|
+
else if (pendingCount >= 2) score += 15;
|
|
263
|
+
else if (pendingCount >= 1) score += 5;
|
|
264
|
+
|
|
265
|
+
return Math.min(100, score);
|
|
266
|
+
}
|