jfl 0.5.0 → 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/dist/commands/context-hub.d.ts +1 -0
- package/dist/commands/context-hub.d.ts.map +1 -1
- package/dist/commands/context-hub.js +246 -2
- package/dist/commands/context-hub.js.map +1 -1
- package/dist/commands/peter.d.ts +2 -0
- package/dist/commands/peter.d.ts.map +1 -1
- package/dist/commands/peter.js +242 -52
- package/dist/commands/peter.js.map +1 -1
- package/dist/commands/setup.d.ts +12 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +322 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/train.d.ts +33 -0
- package/dist/commands/train.d.ts.map +1 -0
- package/dist/commands/train.js +510 -0
- package/dist/commands/train.js.map +1 -0
- package/dist/commands/verify.d.ts +14 -0
- package/dist/commands/verify.d.ts.map +1 -0
- package/dist/commands/verify.js +276 -0
- package/dist/commands/verify.js.map +1 -0
- package/dist/dashboard-static/assets/index-CW9ZxqX8.css +1 -0
- package/dist/dashboard-static/assets/index-DNN__p4K.js +121 -0
- package/dist/dashboard-static/index.html +2 -2
- package/dist/index.js +99 -3
- package/dist/index.js.map +1 -1
- package/dist/lib/agent-session.d.ts.map +1 -1
- package/dist/lib/agent-session.js +12 -4
- package/dist/lib/agent-session.js.map +1 -1
- package/dist/lib/eval-snapshot.js +1 -1
- package/dist/lib/eval-snapshot.js.map +1 -1
- package/dist/lib/pi-sky/bridge.d.ts +55 -0
- package/dist/lib/pi-sky/bridge.d.ts.map +1 -0
- package/dist/lib/pi-sky/bridge.js +264 -0
- package/dist/lib/pi-sky/bridge.js.map +1 -0
- package/dist/lib/pi-sky/cost-monitor.d.ts +21 -0
- package/dist/lib/pi-sky/cost-monitor.d.ts.map +1 -0
- package/dist/lib/pi-sky/cost-monitor.js +126 -0
- package/dist/lib/pi-sky/cost-monitor.js.map +1 -0
- package/dist/lib/pi-sky/eval-sweep.d.ts +27 -0
- package/dist/lib/pi-sky/eval-sweep.d.ts.map +1 -0
- package/dist/lib/pi-sky/eval-sweep.js +141 -0
- package/dist/lib/pi-sky/eval-sweep.js.map +1 -0
- package/dist/lib/pi-sky/event-router.d.ts +32 -0
- package/dist/lib/pi-sky/event-router.d.ts.map +1 -0
- package/dist/lib/pi-sky/event-router.js +176 -0
- package/dist/lib/pi-sky/event-router.js.map +1 -0
- package/dist/lib/pi-sky/experiment.d.ts +9 -0
- package/dist/lib/pi-sky/experiment.d.ts.map +1 -0
- package/dist/lib/pi-sky/experiment.js +83 -0
- package/dist/lib/pi-sky/experiment.js.map +1 -0
- package/dist/lib/pi-sky/index.d.ts +16 -0
- package/dist/lib/pi-sky/index.d.ts.map +1 -0
- package/dist/lib/pi-sky/index.js +16 -0
- package/dist/lib/pi-sky/index.js.map +1 -0
- package/dist/lib/pi-sky/stratus-gate.d.ts +28 -0
- package/dist/lib/pi-sky/stratus-gate.d.ts.map +1 -0
- package/dist/lib/pi-sky/stratus-gate.js +61 -0
- package/dist/lib/pi-sky/stratus-gate.js.map +1 -0
- package/dist/lib/pi-sky/swarm.d.ts +28 -0
- package/dist/lib/pi-sky/swarm.d.ts.map +1 -0
- package/dist/lib/pi-sky/swarm.js +208 -0
- package/dist/lib/pi-sky/swarm.js.map +1 -0
- package/dist/lib/pi-sky/types.d.ts +139 -0
- package/dist/lib/pi-sky/types.d.ts.map +1 -0
- package/dist/lib/pi-sky/types.js +2 -0
- package/dist/lib/pi-sky/types.js.map +1 -0
- package/dist/lib/pi-sky/voice-bridge.d.ts +20 -0
- package/dist/lib/pi-sky/voice-bridge.d.ts.map +1 -0
- package/dist/lib/pi-sky/voice-bridge.js +91 -0
- package/dist/lib/pi-sky/voice-bridge.js.map +1 -0
- package/dist/lib/policy-head.d.ts +16 -1
- package/dist/lib/policy-head.d.ts.map +1 -1
- package/dist/lib/policy-head.js +117 -19
- package/dist/lib/policy-head.js.map +1 -1
- package/dist/lib/predictor.d.ts +10 -0
- package/dist/lib/predictor.d.ts.map +1 -1
- package/dist/lib/predictor.js +46 -7
- package/dist/lib/predictor.js.map +1 -1
- package/dist/lib/setup/agent-generator.d.ts +18 -0
- package/dist/lib/setup/agent-generator.d.ts.map +1 -0
- package/dist/lib/setup/agent-generator.js +114 -0
- package/dist/lib/setup/agent-generator.js.map +1 -0
- package/dist/lib/setup/context-analyzer.d.ts +16 -0
- package/dist/lib/setup/context-analyzer.d.ts.map +1 -0
- package/dist/lib/setup/context-analyzer.js +112 -0
- package/dist/lib/setup/context-analyzer.js.map +1 -0
- package/dist/lib/setup/doc-auditor.d.ts +54 -0
- package/dist/lib/setup/doc-auditor.d.ts.map +1 -0
- package/dist/lib/setup/doc-auditor.js +629 -0
- package/dist/lib/setup/doc-auditor.js.map +1 -0
- package/dist/lib/setup/domain-generator.d.ts +7 -0
- package/dist/lib/setup/domain-generator.d.ts.map +1 -0
- package/dist/lib/setup/domain-generator.js +58 -0
- package/dist/lib/setup/domain-generator.js.map +1 -0
- package/dist/lib/setup/smart-eval-generator.d.ts +38 -0
- package/dist/lib/setup/smart-eval-generator.d.ts.map +1 -0
- package/dist/lib/setup/smart-eval-generator.js +378 -0
- package/dist/lib/setup/smart-eval-generator.js.map +1 -0
- package/dist/lib/setup/smart-recommender.d.ts +63 -0
- package/dist/lib/setup/smart-recommender.d.ts.map +1 -0
- package/dist/lib/setup/smart-recommender.js +329 -0
- package/dist/lib/setup/smart-recommender.js.map +1 -0
- package/dist/lib/setup/spec-generator.d.ts +63 -0
- package/dist/lib/setup/spec-generator.d.ts.map +1 -0
- package/dist/lib/setup/spec-generator.js +310 -0
- package/dist/lib/setup/spec-generator.js.map +1 -0
- package/dist/lib/setup/violation-agent-generator.d.ts +32 -0
- package/dist/lib/setup/violation-agent-generator.d.ts.map +1 -0
- package/dist/lib/setup/violation-agent-generator.js +255 -0
- package/dist/lib/setup/violation-agent-generator.js.map +1 -0
- package/package.json +1 -1
- package/packages/pi/extensions/context.ts +88 -55
- package/packages/pi/extensions/hub-resolver.ts +63 -0
- package/packages/pi/extensions/index.ts +16 -3
- package/packages/pi/extensions/memory-tool.ts +9 -4
- package/packages/pi/extensions/session.ts +68 -16
- package/packages/pi/extensions/tool-renderers.ts +23 -8
- package/scripts/train/requirements.txt +5 -0
- package/scripts/train/train-policy-head.py +477 -0
- package/scripts/train/v2/dataset.py +81 -0
- package/scripts/train/v2/domain.json +18 -0
- package/scripts/train/v2/eval.py +196 -0
- package/scripts/train/v2/generate_data.py +219 -0
- package/scripts/train/v2/infer.py +188 -0
- package/scripts/train/v2/model.py +112 -0
- package/scripts/train/v2/precompute.py +132 -0
- package/scripts/train/v2/train.py +302 -0
- package/scripts/train/v2/transform_buffer.py +227 -0
- package/scripts/train/v2/validate_data.py +115 -0
- package/template/.claude/settings.json +2 -15
- package/template/scripts/session/session-cleanup.sh +2 -11
- package/template/scripts/session/session-end-hub.sh +72 -0
- package/template/scripts/session/session-start-hub.sh +105 -0
- package/dist/dashboard-static/assets/index-B6b867Pv.js +0 -121
- package/dist/dashboard-static/assets/index-Y4BrqxV-.css +0 -1
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @purpose Generate TLA+ specifications from project analysis
|
|
3
|
+
* Scans codebase structure, journal entries, and service configs
|
|
4
|
+
* to produce a formal model that TLC/Apalache can verify.
|
|
5
|
+
*/
|
|
6
|
+
import { existsSync, readFileSync, readdirSync, writeFileSync, mkdirSync } from "fs";
|
|
7
|
+
import { join, basename } from "path";
|
|
8
|
+
/**
|
|
9
|
+
* Scan project structure and journals to extract a system model
|
|
10
|
+
*/
|
|
11
|
+
export function extractSystemModel(projectRoot) {
|
|
12
|
+
const model = {
|
|
13
|
+
services: [],
|
|
14
|
+
stateVariables: [],
|
|
15
|
+
actions: [],
|
|
16
|
+
invariants: [],
|
|
17
|
+
concurrencyPatterns: [],
|
|
18
|
+
};
|
|
19
|
+
// 1. Extract services from services.json
|
|
20
|
+
const servicesPath = join(projectRoot, ".jfl", "services.json");
|
|
21
|
+
if (existsSync(servicesPath)) {
|
|
22
|
+
const services = JSON.parse(readFileSync(servicesPath, "utf-8"));
|
|
23
|
+
for (const [id, svc] of Object.entries(services)) {
|
|
24
|
+
model.services.push({
|
|
25
|
+
name: id,
|
|
26
|
+
type: svc.type || "process",
|
|
27
|
+
port: svc.port,
|
|
28
|
+
dependencies: [], // filled in below
|
|
29
|
+
});
|
|
30
|
+
// Each service has a status variable
|
|
31
|
+
model.stateVariables.push({
|
|
32
|
+
name: `${id}_status`,
|
|
33
|
+
type: "status",
|
|
34
|
+
domain: ["up", "down", "deploying"],
|
|
35
|
+
source: "services.json",
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// 2. Extract agent configs
|
|
40
|
+
const agentsDir = join(projectRoot, ".jfl", "agents");
|
|
41
|
+
if (existsSync(agentsDir)) {
|
|
42
|
+
for (const file of readdirSync(agentsDir).filter(f => f.endsWith(".toml"))) {
|
|
43
|
+
const content = readFileSync(join(agentsDir, file), "utf-8");
|
|
44
|
+
const name = basename(file, ".toml");
|
|
45
|
+
const targetRepo = extractTomlValue(content, "target_repo") || projectRoot;
|
|
46
|
+
const scope = extractTomlValue(content, "scope") || "unknown";
|
|
47
|
+
// Agent status variable
|
|
48
|
+
model.stateVariables.push({
|
|
49
|
+
name: `agent_${name}_status`,
|
|
50
|
+
type: "status",
|
|
51
|
+
domain: ["idle", "scheduled", "running", "eval", "done"],
|
|
52
|
+
source: `agents/${file}`,
|
|
53
|
+
});
|
|
54
|
+
// Agent actions
|
|
55
|
+
model.actions.push({
|
|
56
|
+
name: `Schedule_${name}`,
|
|
57
|
+
preconditions: [`agent_${name}_status = "idle"`, `hub_status = "up"`],
|
|
58
|
+
effects: [`agent_${name}_status`],
|
|
59
|
+
source: `agents/${file}`,
|
|
60
|
+
});
|
|
61
|
+
model.actions.push({
|
|
62
|
+
name: `Run_${name}`,
|
|
63
|
+
preconditions: [`agent_${name}_status = "scheduled"`, `repo_lock_available(${targetRepo})`],
|
|
64
|
+
effects: [`agent_${name}_status`, `repo_locks`],
|
|
65
|
+
source: `agents/${file}`,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// 3. Analyze journals for concurrency patterns
|
|
70
|
+
const journalDir = join(projectRoot, ".jfl", "journal");
|
|
71
|
+
if (existsSync(journalDir)) {
|
|
72
|
+
const sessionFiles = readdirSync(journalDir).filter(f => f.endsWith(".jsonl"));
|
|
73
|
+
const sessions = [];
|
|
74
|
+
for (const file of sessionFiles) {
|
|
75
|
+
const entries = [];
|
|
76
|
+
const content = readFileSync(join(journalDir, file), "utf-8");
|
|
77
|
+
for (const line of content.split("\n").filter(l => l.trim())) {
|
|
78
|
+
try {
|
|
79
|
+
const entry = JSON.parse(line);
|
|
80
|
+
entries.push({
|
|
81
|
+
timestamp: entry.timestamp || 0,
|
|
82
|
+
files: entry.files || [],
|
|
83
|
+
type: entry.type || "unknown",
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
catch { /* skip */ }
|
|
87
|
+
}
|
|
88
|
+
if (entries.length > 0)
|
|
89
|
+
sessions.push(entries);
|
|
90
|
+
}
|
|
91
|
+
// Find overlapping sessions (parallel edits)
|
|
92
|
+
for (let i = 0; i < sessions.length; i++) {
|
|
93
|
+
for (let j = i + 1; j < sessions.length; j++) {
|
|
94
|
+
const overlap = findFileOverlap(sessions[i], sessions[j]);
|
|
95
|
+
if (overlap.length > 0) {
|
|
96
|
+
model.concurrencyPatterns.push({
|
|
97
|
+
type: "parallel_edit",
|
|
98
|
+
description: `Sessions ${i} and ${j} edited ${overlap.length} common files`,
|
|
99
|
+
actors: [`session_${i}`, `session_${j}`],
|
|
100
|
+
resource: overlap[0],
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// 4. Infer invariants from patterns
|
|
107
|
+
if (model.concurrencyPatterns.some(p => p.type === "parallel_edit")) {
|
|
108
|
+
model.invariants.push({
|
|
109
|
+
name: "NoParallelEdits",
|
|
110
|
+
description: "No two agents should edit the same file scope simultaneously",
|
|
111
|
+
formula: `\\A r \\in Repos : Cardinality(repoLocks[r]) <= 1`,
|
|
112
|
+
severity: "critical",
|
|
113
|
+
source: "journal_analysis",
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
// Always add basic invariants
|
|
117
|
+
model.invariants.push({
|
|
118
|
+
name: "HubRequiredForScheduling",
|
|
119
|
+
description: "Agents cannot be scheduled when hub is down",
|
|
120
|
+
formula: `serviceStatus["hub"] = "down" => \\A a \\in Agents : agentStatus[a] \\notin {"running", "eval"}`,
|
|
121
|
+
severity: "critical",
|
|
122
|
+
source: "system_design",
|
|
123
|
+
});
|
|
124
|
+
model.invariants.push({
|
|
125
|
+
name: "LockIntegrity",
|
|
126
|
+
description: "Running agents must hold their repo lock",
|
|
127
|
+
formula: `\\A a \\in Agents : agentStatus[a] \\in {"running", "eval"} => a \\in repoLocks[agentRepo[a]]`,
|
|
128
|
+
severity: "critical",
|
|
129
|
+
source: "system_design",
|
|
130
|
+
});
|
|
131
|
+
return model;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Generate a TLA+ specification from a system model
|
|
135
|
+
*/
|
|
136
|
+
export function generateTLASpec(model, specName) {
|
|
137
|
+
const services = model.services.map(s => `"${s.name}"`).join(", ");
|
|
138
|
+
const agents = model.stateVariables
|
|
139
|
+
.filter(v => v.name.startsWith("agent_") && v.type === "status")
|
|
140
|
+
.map(v => `"${v.name.replace("agent_", "").replace("_status", "")}"`)
|
|
141
|
+
.join(", ");
|
|
142
|
+
let spec = `---- MODULE ${specName} ----
|
|
143
|
+
\\* Auto-generated by jfl setup — ${new Date().toISOString()}
|
|
144
|
+
\\* System model extracted from project analysis
|
|
145
|
+
|
|
146
|
+
EXTENDS Integers, Sequences, FiniteSets
|
|
147
|
+
|
|
148
|
+
CONSTANTS
|
|
149
|
+
Agents,
|
|
150
|
+
Services,
|
|
151
|
+
Repos,
|
|
152
|
+
MaxRounds,
|
|
153
|
+
MaxBufferLen
|
|
154
|
+
|
|
155
|
+
VARIABLES
|
|
156
|
+
serviceStatus,
|
|
157
|
+
agentStatus,
|
|
158
|
+
agentRepo,
|
|
159
|
+
agentRound,
|
|
160
|
+
repoLocks,
|
|
161
|
+
trainingBuffer
|
|
162
|
+
|
|
163
|
+
vars == <<serviceStatus, agentStatus, agentRepo, agentRound, repoLocks, trainingBuffer>>
|
|
164
|
+
|
|
165
|
+
Init ==
|
|
166
|
+
/\\ serviceStatus = [s \\in Services |-> "up"]
|
|
167
|
+
/\\ agentStatus = [a \\in Agents |-> "idle"]
|
|
168
|
+
/\\ agentRepo = [a \\in Agents |-> CHOOSE r \\in Repos : TRUE]
|
|
169
|
+
/\\ agentRound = [a \\in Agents |-> 0]
|
|
170
|
+
/\\ repoLocks = [r \\in Repos |-> {}]
|
|
171
|
+
/\\ trainingBuffer = <<>>
|
|
172
|
+
|
|
173
|
+
\\* --- Service Actions ---
|
|
174
|
+
ServiceCrash(s) ==
|
|
175
|
+
/\\ serviceStatus[s] = "up"
|
|
176
|
+
/\\ serviceStatus' = [serviceStatus EXCEPT ![s] = "down"]
|
|
177
|
+
/\\ UNCHANGED <<agentStatus, agentRepo, agentRound, repoLocks, trainingBuffer>>
|
|
178
|
+
|
|
179
|
+
ServiceRestart(s) ==
|
|
180
|
+
/\\ serviceStatus[s] = "down"
|
|
181
|
+
/\\ serviceStatus' = [serviceStatus EXCEPT ![s] = "up"]
|
|
182
|
+
/\\ UNCHANGED <<agentStatus, agentRepo, agentRound, repoLocks, trainingBuffer>>
|
|
183
|
+
|
|
184
|
+
\\* --- Agent Actions ---
|
|
185
|
+
ScheduleAgent(a) ==
|
|
186
|
+
/\\ agentStatus[a] = "idle"
|
|
187
|
+
/\\ agentRound[a] < MaxRounds
|
|
188
|
+
/\\ serviceStatus["hub"] = "up"
|
|
189
|
+
/\\ agentStatus' = [agentStatus EXCEPT ![a] = "scheduled"]
|
|
190
|
+
/\\ UNCHANGED <<serviceStatus, agentRepo, agentRound, repoLocks, trainingBuffer>>
|
|
191
|
+
|
|
192
|
+
AgentStart(a) ==
|
|
193
|
+
/\\ agentStatus[a] = "scheduled"
|
|
194
|
+
/\\ LET repo == agentRepo[a] IN
|
|
195
|
+
/\\ Cardinality(repoLocks[repo]) < 2
|
|
196
|
+
/\\ repoLocks' = [repoLocks EXCEPT ![repo] = repoLocks[repo] \\cup {a}]
|
|
197
|
+
/\\ agentStatus' = [agentStatus EXCEPT ![a] = "running"]
|
|
198
|
+
/\\ UNCHANGED <<serviceStatus, agentRepo, agentRound, trainingBuffer>>
|
|
199
|
+
|
|
200
|
+
AgentEval(a) ==
|
|
201
|
+
/\\ agentStatus[a] = "running"
|
|
202
|
+
/\\ serviceStatus["hub"] = "up"
|
|
203
|
+
/\\ agentStatus' = [agentStatus EXCEPT ![a] = "eval"]
|
|
204
|
+
/\\ UNCHANGED <<serviceStatus, agentRepo, agentRound, repoLocks, trainingBuffer>>
|
|
205
|
+
|
|
206
|
+
AgentComplete(a) ==
|
|
207
|
+
/\\ agentStatus[a] = "eval"
|
|
208
|
+
/\\ Len(trainingBuffer) < MaxBufferLen
|
|
209
|
+
/\\ LET repo == agentRepo[a] IN
|
|
210
|
+
/\\ repoLocks' = [repoLocks EXCEPT ![repo] = repoLocks[repo] \\ {a}]
|
|
211
|
+
/\\ agentStatus' = [agentStatus EXCEPT ![a] = "done"]
|
|
212
|
+
/\\ agentRound' = [agentRound EXCEPT ![a] = agentRound[a] + 1]
|
|
213
|
+
/\\ \\E score \\in {0, 50, 100} :
|
|
214
|
+
trainingBuffer' = Append(trainingBuffer, [agent |-> a, repo |-> repo, score |-> score])
|
|
215
|
+
/\\ UNCHANGED <<serviceStatus, agentRepo>>
|
|
216
|
+
|
|
217
|
+
AgentReset(a) ==
|
|
218
|
+
/\\ agentStatus[a] = "done"
|
|
219
|
+
/\\ agentRound[a] < MaxRounds
|
|
220
|
+
/\\ agentStatus' = [agentStatus EXCEPT ![a] = "idle"]
|
|
221
|
+
/\\ UNCHANGED <<serviceStatus, agentRepo, agentRound, repoLocks, trainingBuffer>>
|
|
222
|
+
|
|
223
|
+
AgentRecover(a) ==
|
|
224
|
+
/\\ agentStatus[a] \\in {"scheduled", "running", "eval"}
|
|
225
|
+
/\\ serviceStatus["hub"] = "down"
|
|
226
|
+
/\\ LET repo == agentRepo[a] IN
|
|
227
|
+
/\\ repoLocks' = [repoLocks EXCEPT ![repo] = repoLocks[repo] \\ {a}]
|
|
228
|
+
/\\ agentStatus' = [agentStatus EXCEPT ![a] = "idle"]
|
|
229
|
+
/\\ UNCHANGED <<serviceStatus, agentRepo, agentRound, trainingBuffer>>
|
|
230
|
+
|
|
231
|
+
Next ==
|
|
232
|
+
\\/ \\E s \\in Services : ServiceCrash(s)
|
|
233
|
+
\\/ \\E s \\in Services : ServiceRestart(s)
|
|
234
|
+
\\/ \\E a \\in Agents : ScheduleAgent(a)
|
|
235
|
+
\\/ \\E a \\in Agents : AgentStart(a)
|
|
236
|
+
\\/ \\E a \\in Agents : AgentEval(a)
|
|
237
|
+
\\/ \\E a \\in Agents : AgentComplete(a)
|
|
238
|
+
\\/ \\E a \\in Agents : AgentReset(a)
|
|
239
|
+
\\/ \\E a \\in Agents : AgentRecover(a)
|
|
240
|
+
|
|
241
|
+
\\* --- Invariants ---
|
|
242
|
+
`;
|
|
243
|
+
// Add invariants from model
|
|
244
|
+
for (const inv of model.invariants) {
|
|
245
|
+
spec += `\n${inv.name} ==\n ${inv.formula}\n`;
|
|
246
|
+
}
|
|
247
|
+
spec += `
|
|
248
|
+
BoundedConcurrency ==
|
|
249
|
+
\\A r \\in Repos : Cardinality(repoLocks[r]) <= 2
|
|
250
|
+
|
|
251
|
+
BufferBounded ==
|
|
252
|
+
Len(trainingBuffer) <= MaxBufferLen
|
|
253
|
+
|
|
254
|
+
Spec == Init /\\ [][Next]_vars
|
|
255
|
+
|
|
256
|
+
====
|
|
257
|
+
`;
|
|
258
|
+
return spec;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Generate TLC config file
|
|
262
|
+
*/
|
|
263
|
+
export function generateTLCConfig(model, specName) {
|
|
264
|
+
const agents = model.stateVariables
|
|
265
|
+
.filter(v => v.name.startsWith("agent_") && v.type === "status")
|
|
266
|
+
.map(v => `"${v.name.replace("agent_", "").replace("_status", "")}"`);
|
|
267
|
+
const services = model.services.map(s => `"${s.name}"`);
|
|
268
|
+
// Infer repos from agent target_repos
|
|
269
|
+
const repos = [`"default"`]; // always have at least one
|
|
270
|
+
let cfg = `SPECIFICATION Spec\n\n`;
|
|
271
|
+
cfg += `CONSTANTS\n`;
|
|
272
|
+
cfg += ` Agents = {${agents.join(", ")}}\n`;
|
|
273
|
+
cfg += ` Services = {${services.join(", ")}, "hub"}\n`;
|
|
274
|
+
cfg += ` Repos = {${repos.join(", ")}}\n`;
|
|
275
|
+
cfg += ` MaxRounds = 1\n`;
|
|
276
|
+
cfg += ` MaxBufferLen = ${agents.length}\n`;
|
|
277
|
+
cfg += `\n`;
|
|
278
|
+
cfg += `INVARIANTS\n`;
|
|
279
|
+
for (const inv of model.invariants) {
|
|
280
|
+
cfg += ` ${inv.name}\n`;
|
|
281
|
+
}
|
|
282
|
+
cfg += ` BoundedConcurrency\n`;
|
|
283
|
+
cfg += ` BufferBounded\n`;
|
|
284
|
+
return cfg;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Write spec and config to disk, return paths
|
|
288
|
+
*/
|
|
289
|
+
export function writeSpec(projectRoot, model, specName = "SystemSpec") {
|
|
290
|
+
const specDir = join(projectRoot, ".jfl", "specs");
|
|
291
|
+
mkdirSync(specDir, { recursive: true });
|
|
292
|
+
const spec = generateTLASpec(model, specName);
|
|
293
|
+
const cfg = generateTLCConfig(model, specName);
|
|
294
|
+
const specPath = join(specDir, `${specName}.tla`);
|
|
295
|
+
const cfgPath = join(specDir, `${specName}.cfg`);
|
|
296
|
+
writeFileSync(specPath, spec);
|
|
297
|
+
writeFileSync(cfgPath, cfg);
|
|
298
|
+
return { specPath, cfgPath };
|
|
299
|
+
}
|
|
300
|
+
// --- Helpers ---
|
|
301
|
+
function extractTomlValue(content, key) {
|
|
302
|
+
const match = content.match(new RegExp(`${key}\\s*=\\s*"([^"]+)"`));
|
|
303
|
+
return match ? match[1] : null;
|
|
304
|
+
}
|
|
305
|
+
function findFileOverlap(session1, session2) {
|
|
306
|
+
const files1 = session1.flatMap(e => e.files);
|
|
307
|
+
const files2Set = new Set(session2.flatMap(e => e.files));
|
|
308
|
+
return files1.filter(f => files2Set.has(f));
|
|
309
|
+
}
|
|
310
|
+
//# sourceMappingURL=spec-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec-generator.js","sourceRoot":"","sources":["../../../src/lib/setup/spec-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @purpose Generate agent configs from TLC invariant violations
|
|
3
|
+
* Each violation becomes an agent whose eval script checks the invariant
|
|
4
|
+
*/
|
|
5
|
+
interface Violation {
|
|
6
|
+
invariant: string;
|
|
7
|
+
trace: {
|
|
8
|
+
step: number;
|
|
9
|
+
action: string;
|
|
10
|
+
state: Record<string, string>;
|
|
11
|
+
}[];
|
|
12
|
+
}
|
|
13
|
+
interface ViolationAgent {
|
|
14
|
+
name: string;
|
|
15
|
+
metric: string;
|
|
16
|
+
direction: "maximize" | "minimize";
|
|
17
|
+
scope: string;
|
|
18
|
+
evalScript: string;
|
|
19
|
+
evalContent: string;
|
|
20
|
+
tomlContent: string;
|
|
21
|
+
description: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Map a TLC invariant violation to an agent config + eval script
|
|
25
|
+
*/
|
|
26
|
+
export declare function violationToAgent(violation: Violation): ViolationAgent;
|
|
27
|
+
/**
|
|
28
|
+
* Write agent configs and eval scripts from violations
|
|
29
|
+
*/
|
|
30
|
+
export declare function writeViolationAgents(projectRoot: string, violations: Violation[]): string[];
|
|
31
|
+
export {};
|
|
32
|
+
//# sourceMappingURL=violation-agent-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"violation-agent-generator.d.ts","sourceRoot":"","sources":["../../../src/lib/setup/violation-agent-generator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,UAAU,SAAS;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,EAAE,CAAA;CACzE;AAED,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,UAAU,GAAG,UAAU,CAAA;IAClC,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,SAAS,GAAG,cAAc,CAkFrE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,SAAS,EAAE,GACtB,MAAM,EAAE,CAmCV"}
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @purpose Generate agent configs from TLC invariant violations
|
|
3
|
+
* Each violation becomes an agent whose eval script checks the invariant
|
|
4
|
+
*/
|
|
5
|
+
import { mkdirSync, writeFileSync } from "fs";
|
|
6
|
+
import { join } from "path";
|
|
7
|
+
import { generateSmartEval } from "./smart-eval-generator.js";
|
|
8
|
+
/**
|
|
9
|
+
* Map a TLC invariant violation to an agent config + eval script
|
|
10
|
+
*/
|
|
11
|
+
export function violationToAgent(violation) {
|
|
12
|
+
const inv = violation.invariant;
|
|
13
|
+
const trace = violation.trace;
|
|
14
|
+
// Infer what went wrong from the trace
|
|
15
|
+
const lastStep = trace[trace.length - 1];
|
|
16
|
+
const actions = trace.map(t => t.action).filter(a => a !== "Initial");
|
|
17
|
+
switch (inv) {
|
|
18
|
+
case "HumanAgentIsolation":
|
|
19
|
+
return {
|
|
20
|
+
name: "repo-guard",
|
|
21
|
+
metric: "isolation_violations",
|
|
22
|
+
direction: "minimize",
|
|
23
|
+
scope: "coordination",
|
|
24
|
+
evalScript: "eval/repo-guard.sh",
|
|
25
|
+
description: "Prevents human-agent conflicts on shared repos",
|
|
26
|
+
evalContent: generateRepoGuardEval(),
|
|
27
|
+
tomlContent: generateToml("repo-guard", "isolation_violations", "minimize", "coordination", "eval/repo-guard.sh", "Detects and prevents concurrent human+agent edits on the same repo. Generated from TLC invariant violation."),
|
|
28
|
+
};
|
|
29
|
+
case "ScopeIsolation":
|
|
30
|
+
case "NoParallelEdits":
|
|
31
|
+
return {
|
|
32
|
+
name: "scope-lock",
|
|
33
|
+
metric: "lock_violations",
|
|
34
|
+
direction: "minimize",
|
|
35
|
+
scope: "concurrency",
|
|
36
|
+
evalScript: "eval/scope-lock.sh",
|
|
37
|
+
description: "Enforces file scope locking between agents",
|
|
38
|
+
evalContent: generateScopeLockEval(),
|
|
39
|
+
tomlContent: generateToml("scope-lock", "lock_violations", "minimize", "concurrency", "eval/scope-lock.sh", "Enforces mutual exclusion on file scopes. Generated from TLC invariant violation."),
|
|
40
|
+
};
|
|
41
|
+
case "HubRequiredForScheduling":
|
|
42
|
+
case "NoOrphanedAgents":
|
|
43
|
+
return {
|
|
44
|
+
name: "hub-sentinel",
|
|
45
|
+
metric: "stranded_agents",
|
|
46
|
+
direction: "minimize",
|
|
47
|
+
scope: "reliability",
|
|
48
|
+
evalScript: "eval/hub-sentinel.sh",
|
|
49
|
+
description: "Detects and recovers stranded agents when hub crashes",
|
|
50
|
+
evalContent: generateHubSentinelEval(),
|
|
51
|
+
tomlContent: generateToml("hub-sentinel", "stranded_agents", "minimize", "reliability", "eval/hub-sentinel.sh", "Monitors hub health and recovers agents stranded by hub crashes. Generated from TLC invariant violation."),
|
|
52
|
+
};
|
|
53
|
+
case "BoundedConcurrency":
|
|
54
|
+
return {
|
|
55
|
+
name: "concurrency-limiter",
|
|
56
|
+
metric: "over_concurrent_count",
|
|
57
|
+
direction: "minimize",
|
|
58
|
+
scope: "scheduling",
|
|
59
|
+
evalScript: "eval/concurrency-limiter.sh",
|
|
60
|
+
description: "Limits concurrent agents per repo",
|
|
61
|
+
evalContent: generateConcurrencyLimiterEval(),
|
|
62
|
+
tomlContent: generateToml("concurrency-limiter", "over_concurrent_count", "minimize", "scheduling", "eval/concurrency-limiter.sh", "Enforces max concurrent agents per repo. Generated from TLC invariant violation."),
|
|
63
|
+
};
|
|
64
|
+
default:
|
|
65
|
+
return {
|
|
66
|
+
name: `fix-${inv.toLowerCase().replace(/[^a-z0-9]/g, "-")}`,
|
|
67
|
+
metric: `${inv.toLowerCase()}_violations`,
|
|
68
|
+
direction: "minimize",
|
|
69
|
+
scope: "system",
|
|
70
|
+
evalScript: `eval/fix-${inv.toLowerCase()}.sh`,
|
|
71
|
+
description: `Fixes ${inv} invariant violation`,
|
|
72
|
+
evalContent: generateGenericEval(inv),
|
|
73
|
+
tomlContent: generateToml(`fix-${inv.toLowerCase().replace(/[^a-z0-9]/g, "-")}`, `${inv.toLowerCase()}_violations`, "minimize", "system", `eval/fix-${inv.toLowerCase()}.sh`, `Fixes ${inv} invariant violation found by TLC model checker.`),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Write agent configs and eval scripts from violations
|
|
79
|
+
*/
|
|
80
|
+
export function writeViolationAgents(projectRoot, violations) {
|
|
81
|
+
const agentsDir = join(projectRoot, ".jfl", "agents");
|
|
82
|
+
const evalDir = join(projectRoot, "eval");
|
|
83
|
+
mkdirSync(agentsDir, { recursive: true });
|
|
84
|
+
mkdirSync(evalDir, { recursive: true });
|
|
85
|
+
const written = [];
|
|
86
|
+
for (const violation of violations) {
|
|
87
|
+
const agent = violationToAgent(violation);
|
|
88
|
+
// Write TOML config
|
|
89
|
+
const tomlPath = join(agentsDir, `${agent.name}.toml`);
|
|
90
|
+
writeFileSync(tomlPath, agent.tomlContent);
|
|
91
|
+
// Write eval script — use smart generator for real system checks
|
|
92
|
+
const evalPath = join(projectRoot, agent.evalScript);
|
|
93
|
+
const violationCtx = {
|
|
94
|
+
invariant: violation.invariant,
|
|
95
|
+
trace: violation.trace.map((s) => ({
|
|
96
|
+
step: s.step,
|
|
97
|
+
action: s.action,
|
|
98
|
+
state: s.state || {},
|
|
99
|
+
})),
|
|
100
|
+
stateVars: [],
|
|
101
|
+
services: [],
|
|
102
|
+
concurrencyPatterns: [],
|
|
103
|
+
};
|
|
104
|
+
const smartEval = generateSmartEval(projectRoot, violationCtx);
|
|
105
|
+
writeFileSync(evalPath, smartEval, { mode: 0o755 });
|
|
106
|
+
written.push(agent.name);
|
|
107
|
+
}
|
|
108
|
+
return written;
|
|
109
|
+
}
|
|
110
|
+
// --- Template generators ---
|
|
111
|
+
function generateToml(name, metric, direction, scope, evalScript, description) {
|
|
112
|
+
return `# ${name} — Generated from TLC invariant violation
|
|
113
|
+
# ${description}
|
|
114
|
+
|
|
115
|
+
[agent]
|
|
116
|
+
name = "${name}"
|
|
117
|
+
scope = "${scope}"
|
|
118
|
+
metric = "${metric}"
|
|
119
|
+
direction = "${direction}"
|
|
120
|
+
time_budget_seconds = 180
|
|
121
|
+
rounds = 10
|
|
122
|
+
|
|
123
|
+
[eval]
|
|
124
|
+
script = "${evalScript}"
|
|
125
|
+
|
|
126
|
+
[meta]
|
|
127
|
+
source = "tlc_violation"
|
|
128
|
+
generated_at = "${new Date().toISOString()}"
|
|
129
|
+
`;
|
|
130
|
+
}
|
|
131
|
+
function generateRepoGuardEval() {
|
|
132
|
+
return `#!/bin/bash
|
|
133
|
+
# Eval: repo-guard — checks for human-agent isolation violations
|
|
134
|
+
# Generated from TLC HumanAgentIsolation invariant
|
|
135
|
+
|
|
136
|
+
set -euo pipefail
|
|
137
|
+
|
|
138
|
+
VIOLATIONS=0
|
|
139
|
+
|
|
140
|
+
# Check if any agent worktrees overlap with human edit sessions
|
|
141
|
+
for lock_file in .jfl/locks/*.lock 2>/dev/null; do
|
|
142
|
+
[ -f "$lock_file" ] || continue
|
|
143
|
+
REPO=$(cat "$lock_file" | jq -r '.repo // empty')
|
|
144
|
+
AGENT=$(cat "$lock_file" | jq -r '.agent // empty')
|
|
145
|
+
|
|
146
|
+
# Check if human has uncommitted changes in same repo
|
|
147
|
+
if [ -n "$REPO" ] && [ -d "$REPO" ]; then
|
|
148
|
+
HUMAN_CHANGES=$(cd "$REPO" && git diff --name-only 2>/dev/null | wc -l | tr -d ' ')
|
|
149
|
+
if [ "$HUMAN_CHANGES" -gt 0 ] && [ -n "$AGENT" ]; then
|
|
150
|
+
echo "VIOLATION: Agent $AGENT active on $REPO while human has $HUMAN_CHANGES uncommitted changes"
|
|
151
|
+
VIOLATIONS=$((VIOLATIONS + 1))
|
|
152
|
+
fi
|
|
153
|
+
fi
|
|
154
|
+
done
|
|
155
|
+
|
|
156
|
+
echo '{"metric": "isolation_violations", "value": '$VIOLATIONS'}'
|
|
157
|
+
`;
|
|
158
|
+
}
|
|
159
|
+
function generateScopeLockEval() {
|
|
160
|
+
return `#!/bin/bash
|
|
161
|
+
# Eval: scope-lock — checks for concurrent scope access violations
|
|
162
|
+
# Generated from TLC ScopeIsolation invariant
|
|
163
|
+
|
|
164
|
+
set -euo pipefail
|
|
165
|
+
|
|
166
|
+
VIOLATIONS=0
|
|
167
|
+
|
|
168
|
+
# Check agent lock files for overlapping scopes
|
|
169
|
+
declare -A SCOPE_OWNERS
|
|
170
|
+
for lock_file in .jfl/locks/*.lock 2>/dev/null; do
|
|
171
|
+
[ -f "$lock_file" ] || continue
|
|
172
|
+
SCOPE=$(cat "$lock_file" | jq -r '.scope // empty')
|
|
173
|
+
AGENT=$(cat "$lock_file" | jq -r '.agent // empty')
|
|
174
|
+
|
|
175
|
+
if [ -n "$SCOPE" ] && [ -n "\${SCOPE_OWNERS[$SCOPE]+x}" ]; then
|
|
176
|
+
echo "VIOLATION: Scope $SCOPE held by both \${SCOPE_OWNERS[$SCOPE]} and $AGENT"
|
|
177
|
+
VIOLATIONS=$((VIOLATIONS + 1))
|
|
178
|
+
fi
|
|
179
|
+
SCOPE_OWNERS[$SCOPE]=$AGENT
|
|
180
|
+
done
|
|
181
|
+
|
|
182
|
+
echo '{"metric": "lock_violations", "value": '$VIOLATIONS'}'
|
|
183
|
+
`;
|
|
184
|
+
}
|
|
185
|
+
function generateHubSentinelEval() {
|
|
186
|
+
return `#!/bin/bash
|
|
187
|
+
# Eval: hub-sentinel — checks for stranded agents when hub is down
|
|
188
|
+
# Generated from TLC NoOrphanedAgents invariant
|
|
189
|
+
|
|
190
|
+
set -euo pipefail
|
|
191
|
+
|
|
192
|
+
STRANDED=0
|
|
193
|
+
|
|
194
|
+
# Check if hub is responsive
|
|
195
|
+
HUB_PORT=\${JFL_HUB_PORT:-4360}
|
|
196
|
+
if ! curl -s "http://localhost:$HUB_PORT/health" > /dev/null 2>&1; then
|
|
197
|
+
# Hub is down — check for running agents
|
|
198
|
+
for pid_file in .jfl/agents/pids/*.pid 2>/dev/null; do
|
|
199
|
+
[ -f "$pid_file" ] || continue
|
|
200
|
+
PID=$(cat "$pid_file")
|
|
201
|
+
if kill -0 "$PID" 2>/dev/null; then
|
|
202
|
+
AGENT=$(basename "$pid_file" .pid)
|
|
203
|
+
echo "STRANDED: Agent $AGENT (pid $PID) running while hub is down"
|
|
204
|
+
STRANDED=$((STRANDED + 1))
|
|
205
|
+
fi
|
|
206
|
+
done
|
|
207
|
+
fi
|
|
208
|
+
|
|
209
|
+
echo '{"metric": "stranded_agents", "value": '$STRANDED'}'
|
|
210
|
+
`;
|
|
211
|
+
}
|
|
212
|
+
function generateConcurrencyLimiterEval() {
|
|
213
|
+
return `#!/bin/bash
|
|
214
|
+
# Eval: concurrency-limiter — checks for over-concurrent repo access
|
|
215
|
+
# Generated from TLC BoundedConcurrency invariant
|
|
216
|
+
|
|
217
|
+
set -euo pipefail
|
|
218
|
+
|
|
219
|
+
MAX_CONCURRENT=\${JFL_MAX_CONCURRENT:-2}
|
|
220
|
+
OVER_COUNT=0
|
|
221
|
+
|
|
222
|
+
declare -A REPO_COUNTS
|
|
223
|
+
for lock_file in .jfl/locks/*.lock 2>/dev/null; do
|
|
224
|
+
[ -f "$lock_file" ] || continue
|
|
225
|
+
REPO=$(cat "$lock_file" | jq -r '.repo // empty')
|
|
226
|
+
if [ -n "$REPO" ]; then
|
|
227
|
+
REPO_COUNTS[$REPO]=$(( \${REPO_COUNTS[$REPO]:-0} + 1 ))
|
|
228
|
+
if [ "\${REPO_COUNTS[$REPO]}" -gt "$MAX_CONCURRENT" ]; then
|
|
229
|
+
echo "OVER: $REPO has \${REPO_COUNTS[$REPO]} concurrent agents (max $MAX_CONCURRENT)"
|
|
230
|
+
OVER_COUNT=$((OVER_COUNT + 1))
|
|
231
|
+
fi
|
|
232
|
+
fi
|
|
233
|
+
done
|
|
234
|
+
|
|
235
|
+
echo '{"metric": "over_concurrent_count", "value": '$OVER_COUNT'}'
|
|
236
|
+
`;
|
|
237
|
+
}
|
|
238
|
+
function generateGenericEval(invariant) {
|
|
239
|
+
return `#!/bin/bash
|
|
240
|
+
# Eval: fix-${invariant.toLowerCase()} — checks ${invariant} invariant
|
|
241
|
+
# Generated from TLC model checker violation
|
|
242
|
+
|
|
243
|
+
set -euo pipefail
|
|
244
|
+
|
|
245
|
+
# TODO: Implement specific check for ${invariant}
|
|
246
|
+
# The TLC model checker found that this invariant can be violated.
|
|
247
|
+
# This eval script should check the runtime system for the same condition.
|
|
248
|
+
|
|
249
|
+
VIOLATIONS=0
|
|
250
|
+
|
|
251
|
+
# Placeholder check
|
|
252
|
+
echo '{"metric": "${invariant.toLowerCase()}_violations", "value": '$VIOLATIONS'}'
|
|
253
|
+
`;
|
|
254
|
+
}
|
|
255
|
+
//# sourceMappingURL=violation-agent-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"violation-agent-generator.js","sourceRoot":"","sources":["../../../src/lib/setup/violation-agent-generator.ts"],"names":[],"mappings":"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"}
|