@trevonistrevon/pi-loop 0.5.9 → 0.6.1
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/CHANGELOG.md +72 -0
- package/README.md +64 -5
- package/dist/api.d.ts +11 -0
- package/dist/api.js +10 -0
- package/dist/commands/loop-command.d.ts +9 -2
- package/dist/commands/loop-command.js +81 -51
- package/dist/commands/tasks-command.js +3 -3
- package/dist/coordinator.d.ts +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +89 -19
- package/dist/loop-format.d.ts +3 -0
- package/dist/loop-format.js +20 -0
- package/dist/loop-parse.d.ts +1 -0
- package/dist/loop-parse.js +59 -6
- package/dist/loop-reducer.d.ts +13 -1
- package/dist/loop-reducer.js +26 -0
- package/dist/monitor-manager.js +1 -1
- package/dist/notification-reducer.d.ts +2 -0
- package/dist/reducer-backed-store.d.ts +1 -1
- package/dist/reducer-backed-store.js +1 -1
- package/dist/rpc/channels.d.ts +73 -0
- package/dist/rpc/channels.js +30 -0
- package/dist/rpc/cross-extension-rpc.d.ts +59 -0
- package/dist/rpc/cross-extension-rpc.js +117 -0
- package/dist/runtime/loop-events.d.ts +26 -0
- package/dist/runtime/loop-events.js +26 -0
- package/dist/runtime/monitor-ondone-runtime.js +1 -1
- package/dist/runtime/native-task-rpc.d.ts +22 -0
- package/dist/runtime/native-task-rpc.js +50 -0
- package/dist/runtime/notification-runtime.d.ts +2 -1
- package/dist/runtime/notification-runtime.js +19 -7
- package/dist/runtime/task-backlog-runtime.d.ts +5 -1
- package/dist/runtime/task-backlog-runtime.js +14 -7
- package/dist/runtime/task-mutations.d.ts +39 -0
- package/dist/runtime/task-mutations.js +68 -0
- package/dist/runtime/task-rpc.d.ts +4 -0
- package/dist/runtime/task-rpc.js +40 -58
- package/dist/scheduler.js +25 -7
- package/dist/store.d.ts +9 -1
- package/dist/store.js +57 -0
- package/dist/tools/loop-tools.d.ts +8 -0
- package/dist/tools/loop-tools.js +105 -15
- package/dist/tools/monitor-tools.js +1 -3
- package/dist/tools/native-task-tools.d.ts +2 -6
- package/dist/tools/native-task-tools.js +25 -55
- package/dist/tools/tool-result.d.ts +8 -0
- package/dist/tools/tool-result.js +4 -0
- package/dist/trigger-system.js +1 -1
- package/dist/types.d.ts +24 -1
- package/package.json +15 -2
- package/src/api.ts +36 -0
- package/src/commands/loop-command.ts +100 -55
- package/src/commands/tasks-command.ts +3 -3
- package/src/coordinator.ts +1 -1
- package/src/index.ts +92 -19
- package/src/loop-format.ts +22 -0
- package/src/loop-parse.ts +62 -8
- package/src/loop-reducer.ts +41 -1
- package/src/monitor-manager.ts +1 -1
- package/src/notification-reducer.ts +3 -0
- package/src/reducer-backed-store.ts +3 -3
- package/src/rpc/channels.ts +97 -0
- package/src/rpc/cross-extension-rpc.ts +152 -0
- package/src/runtime/loop-events.ts +60 -0
- package/src/runtime/monitor-ondone-runtime.ts +1 -1
- package/src/runtime/native-task-rpc.ts +139 -0
- package/src/runtime/notification-runtime.ts +21 -8
- package/src/runtime/task-backlog-runtime.ts +25 -7
- package/src/runtime/task-mutations.ts +103 -0
- package/src/runtime/task-rpc.ts +48 -54
- package/src/scheduler.ts +25 -8
- package/src/store.ts +59 -2
- package/src/tools/loop-tools.ts +129 -16
- package/src/tools/monitor-tools.ts +1 -4
- package/src/tools/native-task-tools.ts +31 -52
- package/src/tools/tool-result.ts +4 -0
- package/src/trigger-system.ts +5 -5
- package/src/types.ts +29 -1
- package/.release-please-manifest.json +0 -3
- package/AGENTS.md +0 -83
- package/CONTRIBUTING.md +0 -69
- package/Dockerfile +0 -17
- package/benchmarks/experiment-sim.js +0 -30
- package/coverage/base.css +0 -224
- package/coverage/block-navigation.js +0 -87
- package/coverage/coverage-final.json +0 -33
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +0 -176
- package/coverage/prettify.css +0 -1
- package/coverage/prettify.js +0 -2
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +0 -210
- package/coverage/src/commands/index.html +0 -131
- package/coverage/src/commands/loop-command.ts.html +0 -634
- package/coverage/src/commands/tasks-command.ts.html +0 -490
- package/coverage/src/coordinator.ts.html +0 -430
- package/coverage/src/goal-coordinator.ts.html +0 -259
- package/coverage/src/goal-reducer.ts.html +0 -982
- package/coverage/src/goal-store.ts.html +0 -742
- package/coverage/src/goal-verifier.ts.html +0 -808
- package/coverage/src/index.html +0 -386
- package/coverage/src/index.ts.html +0 -1111
- package/coverage/src/loop-parse.ts.html +0 -574
- package/coverage/src/loop-reducer.ts.html +0 -559
- package/coverage/src/monitor-completion-coordinator.ts.html +0 -157
- package/coverage/src/monitor-manager.ts.html +0 -940
- package/coverage/src/monitor-reducer.ts.html +0 -583
- package/coverage/src/notification-reducer.ts.html +0 -550
- package/coverage/src/reducer-backed-store.ts.html +0 -589
- package/coverage/src/runtime/index.html +0 -206
- package/coverage/src/runtime/monitor-ondone-runtime.ts.html +0 -310
- package/coverage/src/runtime/notification-runtime.ts.html +0 -721
- package/coverage/src/runtime/scope.ts.html +0 -196
- package/coverage/src/runtime/session-runtime.ts.html +0 -679
- package/coverage/src/runtime/task-backlog-runtime.ts.html +0 -574
- package/coverage/src/runtime/task-events.ts.html +0 -208
- package/coverage/src/runtime/task-rpc.ts.html +0 -541
- package/coverage/src/scheduler.ts.html +0 -400
- package/coverage/src/store.ts.html +0 -667
- package/coverage/src/task-backlog-coordinator.ts.html +0 -181
- package/coverage/src/task-reducer.ts.html +0 -550
- package/coverage/src/task-store.ts.html +0 -526
- package/coverage/src/tools/index.html +0 -146
- package/coverage/src/tools/loop-tools.ts.html +0 -1000
- package/coverage/src/tools/monitor-tools.ts.html +0 -547
- package/coverage/src/tools/native-task-tools.ts.html +0 -556
- package/coverage/src/trigger-system.ts.html +0 -547
- package/coverage/src/ui/index.html +0 -116
- package/coverage/src/ui/widget.ts.html +0 -292
- package/dist/goal-coordinator.d.ts +0 -22
- package/dist/goal-coordinator.js +0 -28
- package/dist/goal-reducer.d.ts +0 -98
- package/dist/goal-reducer.js +0 -190
- package/dist/goal-store.d.ts +0 -22
- package/dist/goal-store.js +0 -188
- package/dist/goal-types.d.ts +0 -82
- package/dist/goal-types.js +0 -1
- package/dist/goal-verifier.d.ts +0 -20
- package/dist/goal-verifier.js +0 -198
- package/docker-compose.yml +0 -12
- package/docs/architecture/goal-state-schema.md +0 -505
- package/docs/architecture/state-machine-migration.md +0 -546
- package/docs/architecture/state-machine-reducer-event-model.md +0 -823
- package/docs/architecture/state-machine-test-matrix.md +0 -249
- package/docs/architecture/state-machine-transition-map.md +0 -436
- package/release-please-config.json +0 -9
- package/src/goal-coordinator.ts +0 -58
- package/src/goal-reducer.ts +0 -299
- package/src/goal-store.ts +0 -219
- package/src/goal-types.ts +0 -104
- package/src/goal-verifier.ts +0 -241
- package/vitest.config.ts +0 -29
package/src/goal-verifier.ts
DELETED
|
@@ -1,241 +0,0 @@
|
|
|
1
|
-
import type { ReducerEffect, ReducerEvent } from "./coordinator.js";
|
|
2
|
-
import type { GoalEntry, GoalProgressSnapshot } from "./goal-types.js";
|
|
3
|
-
import type { LoopReducerState } from "./loop-reducer.js";
|
|
4
|
-
import type { MonitorReducerState } from "./monitor-reducer.js";
|
|
5
|
-
import type { TaskReducerState } from "./task-reducer.js";
|
|
6
|
-
import type { TaskEntry } from "./task-types.js";
|
|
7
|
-
import type { LoopEntry, MonitorEntry } from "./types.js";
|
|
8
|
-
|
|
9
|
-
export interface GoalVerifierInput {
|
|
10
|
-
goal: GoalEntry;
|
|
11
|
-
taskState: TaskReducerState;
|
|
12
|
-
loopState: LoopReducerState;
|
|
13
|
-
monitorState: MonitorReducerState;
|
|
14
|
-
at: number;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export interface GoalVerifierResult {
|
|
18
|
-
progress: GoalProgressSnapshot;
|
|
19
|
-
verdict: "passed" | "failed" | "blocked";
|
|
20
|
-
reason: string;
|
|
21
|
-
effects: ReducerEffect[];
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function uniqueById<T extends { id: string }>(items: T[]): T[] {
|
|
25
|
-
const seen = new Set<string>();
|
|
26
|
-
const result: T[] = [];
|
|
27
|
-
for (const item of items) {
|
|
28
|
-
if (seen.has(item.id)) continue;
|
|
29
|
-
seen.add(item.id);
|
|
30
|
-
result.push(item);
|
|
31
|
-
}
|
|
32
|
-
return result;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function selectTasks(goal: GoalEntry, taskState: TaskReducerState): TaskEntry[] {
|
|
36
|
-
const selected: TaskEntry[] = [];
|
|
37
|
-
for (const id of goal.scope.taskIds ?? []) {
|
|
38
|
-
const task = taskState.tasksById[id];
|
|
39
|
-
if (task) selected.push(task);
|
|
40
|
-
}
|
|
41
|
-
for (const prefix of goal.scope.subjectPrefixes ?? []) {
|
|
42
|
-
for (const task of Object.values(taskState.tasksById)) {
|
|
43
|
-
if (task.subject.startsWith(prefix)) selected.push(task);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
return uniqueById(selected);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function selectLoops(goal: GoalEntry, loopState: LoopReducerState): LoopEntry[] {
|
|
50
|
-
const selected: LoopEntry[] = [];
|
|
51
|
-
for (const id of goal.scope.loopIds ?? []) {
|
|
52
|
-
const loop = loopState.loopsById[id];
|
|
53
|
-
if (loop) selected.push(loop);
|
|
54
|
-
}
|
|
55
|
-
return uniqueById(selected);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function selectMonitors(goal: GoalEntry, monitorState: MonitorReducerState): MonitorEntry[] {
|
|
59
|
-
const selected: MonitorEntry[] = [];
|
|
60
|
-
for (const id of goal.scope.monitorIds ?? []) {
|
|
61
|
-
const monitor = monitorState.monitorsById[id];
|
|
62
|
-
if (monitor) selected.push(monitor);
|
|
63
|
-
}
|
|
64
|
-
return uniqueById(selected);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export function projectGoalProgress(
|
|
68
|
-
goal: GoalEntry,
|
|
69
|
-
taskState: TaskReducerState,
|
|
70
|
-
loopState: LoopReducerState,
|
|
71
|
-
monitorState: MonitorReducerState,
|
|
72
|
-
): GoalProgressSnapshot {
|
|
73
|
-
const tasks = selectTasks(goal, taskState);
|
|
74
|
-
const loops = selectLoops(goal, loopState);
|
|
75
|
-
const monitors = selectMonitors(goal, monitorState);
|
|
76
|
-
|
|
77
|
-
const timestamps: number[] = [];
|
|
78
|
-
for (const task of tasks) timestamps.push(task.updatedAt);
|
|
79
|
-
for (const loop of loops) timestamps.push(loop.updatedAt);
|
|
80
|
-
for (const monitor of monitors) timestamps.push(monitor.completedAt ?? monitor.startedAt);
|
|
81
|
-
|
|
82
|
-
return {
|
|
83
|
-
totalTasks: tasks.length,
|
|
84
|
-
pendingTasks: tasks.filter(task => task.status === "pending").length,
|
|
85
|
-
inProgressTasks: tasks.filter(task => task.status === "in_progress").length,
|
|
86
|
-
completedTasks: tasks.filter(task => task.status === "completed").length,
|
|
87
|
-
activeLoops: loops.filter(loop => loop.status === "active").length,
|
|
88
|
-
pausedLoops: loops.filter(loop => loop.status === "paused").length,
|
|
89
|
-
runningMonitors: monitors.filter(monitor => monitor.status === "running").length,
|
|
90
|
-
completedMonitors: monitors.filter(monitor => monitor.status === "completed").length,
|
|
91
|
-
erroredMonitors: monitors.filter(monitor => monitor.status === "error").length,
|
|
92
|
-
stoppedMonitors: monitors.filter(monitor => monitor.status === "stopped").length,
|
|
93
|
-
lastProgressAt: timestamps.length > 0 ? Math.max(...timestamps) : undefined,
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
function dispatchEffect(event: ReducerEvent): ReducerEffect<"DISPATCH_EVENT", { event: ReducerEvent }> {
|
|
98
|
-
return {
|
|
99
|
-
type: "DISPATCH_EVENT",
|
|
100
|
-
entityType: "goal",
|
|
101
|
-
entityId: event.entityId,
|
|
102
|
-
payload: { event },
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function buildEffects(goal: GoalEntry, at: number, progress: GoalProgressSnapshot, resultType: string, reason: string) {
|
|
107
|
-
return [
|
|
108
|
-
dispatchEffect({
|
|
109
|
-
type: "GOAL_VERIFICATION_STARTED",
|
|
110
|
-
at,
|
|
111
|
-
source: "coordinator",
|
|
112
|
-
entityType: "goal",
|
|
113
|
-
entityId: goal.id,
|
|
114
|
-
payload: { id: goal.id },
|
|
115
|
-
}),
|
|
116
|
-
dispatchEffect({
|
|
117
|
-
type: "GOAL_PROGRESS_RECORDED",
|
|
118
|
-
at,
|
|
119
|
-
source: "coordinator",
|
|
120
|
-
entityType: "goal",
|
|
121
|
-
entityId: goal.id,
|
|
122
|
-
payload: { id: goal.id, progress },
|
|
123
|
-
}),
|
|
124
|
-
dispatchEffect({
|
|
125
|
-
type: resultType,
|
|
126
|
-
at,
|
|
127
|
-
source: "coordinator",
|
|
128
|
-
entityType: "goal",
|
|
129
|
-
entityId: goal.id,
|
|
130
|
-
payload: { id: goal.id, reason, progress },
|
|
131
|
-
}),
|
|
132
|
-
];
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
export function verifyGoal(input: GoalVerifierInput): GoalVerifierResult {
|
|
136
|
-
const { goal, taskState, loopState, monitorState, at } = input;
|
|
137
|
-
const progress = projectGoalProgress(goal, taskState, loopState, monitorState);
|
|
138
|
-
|
|
139
|
-
if (goal.criteria.failure?.maxVerificationFailures !== undefined
|
|
140
|
-
&& goal.verification.failures >= goal.criteria.failure.maxVerificationFailures) {
|
|
141
|
-
return {
|
|
142
|
-
progress,
|
|
143
|
-
verdict: "failed",
|
|
144
|
-
reason: "maximum verification failures reached",
|
|
145
|
-
effects: buildEffects(goal, at, progress, "GOAL_FAILED", "maximum verification failures reached"),
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
for (const monitorId of goal.criteria.failure?.anyMonitorIdsErrored ?? []) {
|
|
150
|
-
if (monitorState.monitorsById[monitorId]?.status === "error") {
|
|
151
|
-
return {
|
|
152
|
-
progress,
|
|
153
|
-
verdict: "failed",
|
|
154
|
-
reason: `monitor #${monitorId} errored`,
|
|
155
|
-
effects: buildEffects(goal, at, progress, "GOAL_FAILED", `monitor #${monitorId} errored`),
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
for (const taskId of goal.criteria.failure?.failIfTaskIdsDeleted ?? []) {
|
|
161
|
-
if (!taskState.tasksById[taskId]) {
|
|
162
|
-
return {
|
|
163
|
-
progress,
|
|
164
|
-
verdict: "failed",
|
|
165
|
-
reason: `task #${taskId} missing`,
|
|
166
|
-
effects: buildEffects(goal, at, progress, "GOAL_FAILED", `task #${taskId} missing`),
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
const requiredTasksDone = (goal.criteria.success.requiredTaskIds ?? [])
|
|
172
|
-
.every(taskId => taskState.tasksById[taskId]?.status === "completed");
|
|
173
|
-
const requiredMonitorsDone = (goal.criteria.success.requiredMonitorIdsCompleted ?? [])
|
|
174
|
-
.every(monitorId => monitorState.monitorsById[monitorId]?.status === "completed");
|
|
175
|
-
const requiredLoopsPresent = (goal.criteria.success.requiredLoopIdsPresent ?? [])
|
|
176
|
-
.every(loopId => Boolean(loopState.loopsById[loopId]));
|
|
177
|
-
const minCompletedTasksMet = progress.completedTasks >= (goal.criteria.success.minCompletedTasks ?? 0);
|
|
178
|
-
const noPendingWork = !goal.criteria.success.requireNoPendingTasksInScope
|
|
179
|
-
|| (progress.pendingTasks === 0 && progress.inProgressTasks === 0);
|
|
180
|
-
const latestVerificationPass = !goal.criteria.success.requireLatestVerificationPass
|
|
181
|
-
|| goal.verificationStatus === "verified";
|
|
182
|
-
|
|
183
|
-
const success = requiredTasksDone
|
|
184
|
-
&& requiredMonitorsDone
|
|
185
|
-
&& requiredLoopsPresent
|
|
186
|
-
&& minCompletedTasksMet
|
|
187
|
-
&& noPendingWork
|
|
188
|
-
&& latestVerificationPass;
|
|
189
|
-
|
|
190
|
-
if (success) {
|
|
191
|
-
return {
|
|
192
|
-
progress,
|
|
193
|
-
verdict: "passed",
|
|
194
|
-
reason: "success criteria satisfied",
|
|
195
|
-
effects: buildEffects(goal, at, progress, "GOAL_VERIFICATION_PASSED", "success criteria satisfied"),
|
|
196
|
-
};
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
if (goal.criteria.blocked?.blockedIfRequiredLoopMissing && !requiredLoopsPresent) {
|
|
200
|
-
return {
|
|
201
|
-
progress,
|
|
202
|
-
verdict: "blocked",
|
|
203
|
-
reason: "required loop missing",
|
|
204
|
-
effects: buildEffects(goal, at, progress, "GOAL_BLOCKED", "required loop missing"),
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
if (
|
|
209
|
-
goal.criteria.blocked?.blockedIfNoScopedProgressSinceMs !== undefined
|
|
210
|
-
&& progress.lastProgressAt !== undefined
|
|
211
|
-
&& at - progress.lastProgressAt >= goal.criteria.blocked.blockedIfNoScopedProgressSinceMs
|
|
212
|
-
) {
|
|
213
|
-
return {
|
|
214
|
-
progress,
|
|
215
|
-
verdict: "blocked",
|
|
216
|
-
reason: "no scoped progress within configured interval",
|
|
217
|
-
effects: buildEffects(goal, at, progress, "GOAL_BLOCKED", "no scoped progress within configured interval"),
|
|
218
|
-
};
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
if (
|
|
222
|
-
goal.criteria.blocked?.blockedIfAllTasksCompletedButVerificationFails
|
|
223
|
-
&& progress.totalTasks > 0
|
|
224
|
-
&& progress.pendingTasks === 0
|
|
225
|
-
&& progress.inProgressTasks === 0
|
|
226
|
-
) {
|
|
227
|
-
return {
|
|
228
|
-
progress,
|
|
229
|
-
verdict: "blocked",
|
|
230
|
-
reason: "all scoped tasks completed but verification has not passed",
|
|
231
|
-
effects: buildEffects(goal, at, progress, "GOAL_BLOCKED", "all scoped tasks completed but verification has not passed"),
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
return {
|
|
236
|
-
progress,
|
|
237
|
-
verdict: "failed",
|
|
238
|
-
reason: "success criteria not yet satisfied",
|
|
239
|
-
effects: buildEffects(goal, at, progress, "GOAL_VERIFICATION_FAILED", "success criteria not yet satisfied"),
|
|
240
|
-
};
|
|
241
|
-
}
|
package/vitest.config.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from "vitest/config";
|
|
2
|
-
|
|
3
|
-
export default defineConfig({
|
|
4
|
-
test: {
|
|
5
|
-
environment: "node",
|
|
6
|
-
include: ["test/**/*.test.ts"],
|
|
7
|
-
exclude: ["node_modules", "dist"],
|
|
8
|
-
// CI runners are slower than local; 15s gives real-child-process
|
|
9
|
-
// tests (monitor stop, lifecycle) enough headroom.
|
|
10
|
-
testTimeout: 15000,
|
|
11
|
-
hookTimeout: 15000,
|
|
12
|
-
coverage: {
|
|
13
|
-
provider: "v8",
|
|
14
|
-
reporter: ["text-summary", "html", "json"],
|
|
15
|
-
include: ["src/**/*.ts"],
|
|
16
|
-
// Type-only modules and test helpers carry no executable logic worth gating.
|
|
17
|
-
exclude: ["src/**/*-types.ts", "src/types.ts"],
|
|
18
|
-
// Floors set just below current actuals (stmts 84%, branches 75%,
|
|
19
|
-
// funcs 95%, lines 86%) to catch regressions. Raised in Phase 4 after the
|
|
20
|
-
// runtime/ + tools/ suites landed.
|
|
21
|
-
thresholds: {
|
|
22
|
-
statements: 82,
|
|
23
|
-
branches: 73,
|
|
24
|
-
functions: 94,
|
|
25
|
-
lines: 84,
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
});
|