erdos-problems 0.2.0 → 0.2.2
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/README.md +88 -3
- package/docs/RESEARCH_LOOP.md +7 -0
- package/package.json +1 -1
- package/packs/graph-theory/README.md +17 -0
- package/packs/graph-theory/problems/1008/CHECKPOINT_TEMPLATE.md +9 -0
- package/packs/graph-theory/problems/1008/CONTEXT.md +9 -0
- package/packs/graph-theory/problems/1008/FRONTIER_NOTE.md +8 -0
- package/packs/graph-theory/problems/1008/OPS_DETAILS.yaml +25 -0
- package/packs/graph-theory/problems/1008/REPORT_TEMPLATE.md +9 -0
- package/packs/graph-theory/problems/1008/ROUTE_HISTORY.md +5 -0
- package/packs/graph-theory/problems/1008/ROUTE_PACKET.yaml +13 -0
- package/packs/graph-theory/problems/1008/context.yaml +27 -0
- package/packs/graph-theory/problems/19/CHECKPOINT_TEMPLATE.md +9 -0
- package/packs/graph-theory/problems/19/CONTEXT.md +9 -0
- package/packs/graph-theory/problems/19/FRONTIER_NOTE.md +8 -0
- package/packs/graph-theory/problems/19/OPS_DETAILS.yaml +25 -0
- package/packs/graph-theory/problems/19/REPORT_TEMPLATE.md +9 -0
- package/packs/graph-theory/problems/19/ROUTE_HISTORY.md +5 -0
- package/packs/graph-theory/problems/19/ROUTE_PACKET.yaml +13 -0
- package/packs/graph-theory/problems/19/context.yaml +25 -0
- package/packs/graph-theory/problems/22/CHECKPOINT_TEMPLATE.md +9 -0
- package/packs/graph-theory/problems/22/CONTEXT.md +9 -0
- package/packs/graph-theory/problems/22/FRONTIER_NOTE.md +8 -0
- package/packs/graph-theory/problems/22/OPS_DETAILS.yaml +25 -0
- package/packs/graph-theory/problems/22/REPORT_TEMPLATE.md +9 -0
- package/packs/graph-theory/problems/22/ROUTE_HISTORY.md +5 -0
- package/packs/graph-theory/problems/22/ROUTE_PACKET.yaml +13 -0
- package/packs/graph-theory/problems/22/context.yaml +26 -0
- package/packs/number-theory/README.md +16 -9
- package/packs/number-theory/problems/1/CHECKPOINT_TEMPLATE.md +7 -0
- package/packs/number-theory/problems/1/FRONTIER_NOTE.md +8 -0
- package/packs/number-theory/problems/1/OPS_DETAILS.yaml +25 -0
- package/packs/number-theory/problems/1/REPORT_TEMPLATE.md +7 -0
- package/packs/number-theory/problems/1/ROUTE_HISTORY.md +5 -0
- package/packs/number-theory/problems/1/ROUTE_PACKET.yaml +13 -0
- package/packs/number-theory/problems/1/context.yaml +10 -10
- package/packs/number-theory/problems/2/CHECKPOINT_TEMPLATE.md +7 -0
- package/packs/number-theory/problems/2/FRONTIER_NOTE.md +8 -0
- package/packs/number-theory/problems/2/OPS_DETAILS.yaml +25 -0
- package/packs/number-theory/problems/2/REPORT_TEMPLATE.md +7 -0
- package/packs/number-theory/problems/2/ROUTE_HISTORY.md +5 -0
- package/packs/number-theory/problems/2/ROUTE_PACKET.yaml +13 -0
- package/packs/number-theory/problems/2/context.yaml +11 -11
- package/packs/sunflower/README.md +2 -2
- package/packs/sunflower/problems/536/CHECKPOINT_TEMPLATE.md +7 -0
- package/packs/sunflower/problems/536/FRONTIER_NOTE.md +8 -0
- package/packs/sunflower/problems/536/REPORT_TEMPLATE.md +7 -0
- package/packs/sunflower/problems/536/ROUTE_HISTORY.md +5 -0
- package/packs/sunflower/problems/856/CHECKPOINT_TEMPLATE.md +7 -0
- package/packs/sunflower/problems/856/FRONTIER_NOTE.md +8 -0
- package/packs/sunflower/problems/856/REPORT_TEMPLATE.md +7 -0
- package/packs/sunflower/problems/856/ROUTE_HISTORY.md +5 -0
- package/src/cli/index.js +25 -8
- package/src/commands/archive.js +10 -1
- package/src/commands/cluster.js +19 -1
- package/src/commands/graph-theory.js +180 -0
- package/src/commands/number-theory.js +304 -0
- package/src/commands/pull.js +56 -4
- package/src/commands/workspace.js +55 -1
- package/src/runtime/graph-theory.js +167 -0
- package/src/runtime/number-theory.js +229 -0
- package/src/runtime/state.js +62 -0
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
import { getProblem } from '../atlas/catalog.js';
|
|
2
|
+
import {
|
|
3
|
+
buildNumberTheoryStatusSnapshot,
|
|
4
|
+
getNumberTheoryAtomSnapshot,
|
|
5
|
+
getNumberTheoryRouteSnapshot,
|
|
6
|
+
getNumberTheoryTicketSnapshot,
|
|
7
|
+
} from '../runtime/number-theory.js';
|
|
8
|
+
import { readCurrentProblem } from '../runtime/workspace.js';
|
|
9
|
+
|
|
10
|
+
function resolveNumberTheoryProblem(problemId) {
|
|
11
|
+
const resolvedId = problemId ?? readCurrentProblem();
|
|
12
|
+
if (!resolvedId) {
|
|
13
|
+
return { error: 'Missing problem id and no active problem is selected.' };
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const problem = getProblem(resolvedId);
|
|
17
|
+
if (!problem) {
|
|
18
|
+
return { error: `Unknown problem: ${resolvedId}` };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (problem.cluster !== 'number-theory') {
|
|
22
|
+
return { error: `Problem ${resolvedId} is not in the number-theory pack.` };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return { problem };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function parseArgs(args) {
|
|
29
|
+
const parsed = {
|
|
30
|
+
problemId: null,
|
|
31
|
+
asJson: false,
|
|
32
|
+
entityId: null,
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
for (const token of args) {
|
|
36
|
+
if (token === '--json') {
|
|
37
|
+
parsed.asJson = true;
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (!parsed.problemId) {
|
|
41
|
+
parsed.problemId = token;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (!parsed.entityId) {
|
|
45
|
+
parsed.entityId = token;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
return { error: `Unknown number-theory option: ${token}` };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return parsed;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function printStatus(snapshot) {
|
|
55
|
+
console.log(`${snapshot.displayName} number-theory harness`);
|
|
56
|
+
console.log(`Family role: ${snapshot.familyRole}`);
|
|
57
|
+
console.log(`Harness profile: ${snapshot.harnessProfile}`);
|
|
58
|
+
console.log(`Site status: ${snapshot.siteStatus}`);
|
|
59
|
+
console.log(`Archive mode: ${snapshot.archiveMode ?? '(none)'}`);
|
|
60
|
+
console.log(`Active route: ${snapshot.activeRoute ?? '(none)'}`);
|
|
61
|
+
console.log(`Route breakthrough: ${snapshot.routeBreakthrough ? 'yes' : 'no'}`);
|
|
62
|
+
console.log(`Open problem: ${snapshot.openProblem ? 'yes' : 'no'}`);
|
|
63
|
+
console.log(`Problem solved: ${snapshot.problemSolved ? 'yes' : 'no'}`);
|
|
64
|
+
console.log(`Frontier label: ${snapshot.frontierLabel}`);
|
|
65
|
+
console.log(`Frontier detail: ${snapshot.frontierDetail}`);
|
|
66
|
+
console.log(`Checkpoint focus: ${snapshot.checkpointFocus ?? '(none)'}`);
|
|
67
|
+
console.log(`Next honest move: ${snapshot.nextHonestMove}`);
|
|
68
|
+
console.log(`Route packet present: ${snapshot.routePacketPresent ? 'yes' : 'no'}`);
|
|
69
|
+
if (snapshot.routePacket?.route_packet_id) {
|
|
70
|
+
console.log(`Route packet id: ${snapshot.routePacket.route_packet_id}`);
|
|
71
|
+
}
|
|
72
|
+
console.log(`Frontier note: ${snapshot.frontierNotePresent ? snapshot.frontierNotePath : '(missing)'}`);
|
|
73
|
+
console.log(`Route history: ${snapshot.routeHistoryPresent ? snapshot.routeHistoryPath : '(missing)'}`);
|
|
74
|
+
console.log(`Checkpoint template: ${snapshot.checkpointTemplatePresent ? snapshot.checkpointTemplatePath : '(missing)'}`);
|
|
75
|
+
console.log(`Report template: ${snapshot.reportTemplatePresent ? snapshot.reportTemplatePath : '(missing)'}`);
|
|
76
|
+
console.log(`Ops details present: ${snapshot.opsDetailsPresent ? 'yes' : 'no'}`);
|
|
77
|
+
console.log(`Active ticket: ${snapshot.activeTicketDetail?.ticket_id ?? '(none)'}`);
|
|
78
|
+
console.log(`Ready atoms: ${snapshot.readyAtomCount}`);
|
|
79
|
+
if (snapshot.firstReadyAtom) {
|
|
80
|
+
console.log(`First ready atom: ${snapshot.firstReadyAtom.atom_id} — ${snapshot.firstReadyAtom.title}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function printFrontier(snapshot) {
|
|
85
|
+
console.log(`${snapshot.displayName} number-theory frontier`);
|
|
86
|
+
console.log(`Active route: ${snapshot.activeRoute ?? '(none)'}`);
|
|
87
|
+
console.log(`Frontier label: ${snapshot.frontierLabel}`);
|
|
88
|
+
console.log(`Frontier detail: ${snapshot.frontierDetail}`);
|
|
89
|
+
console.log(`Checkpoint focus: ${snapshot.checkpointFocus ?? '(none)'}`);
|
|
90
|
+
console.log(`Next honest move: ${snapshot.nextHonestMove}`);
|
|
91
|
+
console.log(`Open problem: ${snapshot.openProblem ? 'yes' : 'no'}`);
|
|
92
|
+
console.log(`Archive mode: ${snapshot.archiveMode ?? '(none)'}`);
|
|
93
|
+
console.log(`Frontier note: ${snapshot.frontierNotePresent ? snapshot.frontierNotePath : '(missing)'}`);
|
|
94
|
+
console.log(`Route history: ${snapshot.routeHistoryPresent ? snapshot.routeHistoryPath : '(missing)'}`);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function printRoutes(snapshot) {
|
|
98
|
+
console.log(`${snapshot.displayName} number-theory routes`);
|
|
99
|
+
console.log(`Active route: ${snapshot.activeRoute ?? '(none)'}`);
|
|
100
|
+
if (!snapshot.opsDetails?.routes?.length) {
|
|
101
|
+
console.log('Routes: none recorded.');
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
for (const route of snapshot.opsDetails.routes) {
|
|
105
|
+
const flags = [];
|
|
106
|
+
if (route.route_id === snapshot.activeRoute) {
|
|
107
|
+
flags.push('active');
|
|
108
|
+
}
|
|
109
|
+
if (route.status) {
|
|
110
|
+
flags.push(route.status);
|
|
111
|
+
}
|
|
112
|
+
console.log(`- ${route.route_id}${flags.length > 0 ? ` [${flags.join(', ')}]` : ''}`);
|
|
113
|
+
if (route.title) {
|
|
114
|
+
console.log(` title: ${route.title}`);
|
|
115
|
+
}
|
|
116
|
+
if (route.summary) {
|
|
117
|
+
console.log(` summary: ${route.summary}`);
|
|
118
|
+
}
|
|
119
|
+
if (route.why_now) {
|
|
120
|
+
console.log(` why now: ${route.why_now}`);
|
|
121
|
+
}
|
|
122
|
+
if (route.next_move) {
|
|
123
|
+
console.log(` next move: ${route.next_move}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function printTickets(snapshot) {
|
|
129
|
+
console.log(`${snapshot.displayName} number-theory tickets`);
|
|
130
|
+
if (!snapshot.opsDetails?.tickets?.length) {
|
|
131
|
+
console.log('Tickets: none recorded.');
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
console.log(`Active ticket: ${snapshot.activeTicketDetail?.ticket_id ?? '(none)'}`);
|
|
135
|
+
for (const ticket of snapshot.opsDetails.tickets) {
|
|
136
|
+
const flags = [];
|
|
137
|
+
if (ticket.ticket_id === snapshot.activeTicketDetail?.ticket_id) {
|
|
138
|
+
flags.push('active');
|
|
139
|
+
}
|
|
140
|
+
if (ticket.status) {
|
|
141
|
+
flags.push(ticket.status);
|
|
142
|
+
}
|
|
143
|
+
console.log(`- ${ticket.ticket_id}${flags.length > 0 ? ` [${flags.join(', ')}]` : ''}`);
|
|
144
|
+
if (ticket.title) {
|
|
145
|
+
console.log(` title: ${ticket.title}`);
|
|
146
|
+
}
|
|
147
|
+
if (ticket.summary) {
|
|
148
|
+
console.log(` summary: ${ticket.summary}`);
|
|
149
|
+
}
|
|
150
|
+
if (ticket.current_blocker) {
|
|
151
|
+
console.log(` blocker: ${ticket.current_blocker}`);
|
|
152
|
+
}
|
|
153
|
+
if (ticket.next_move) {
|
|
154
|
+
console.log(` next move: ${ticket.next_move}`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function printRouteDetail(snapshot) {
|
|
160
|
+
const route = snapshot.routeDetail;
|
|
161
|
+
console.log(`${snapshot.displayName} number-theory route ${snapshot.routeId}`);
|
|
162
|
+
console.log(`Title: ${route.title ?? snapshot.routeId}`);
|
|
163
|
+
console.log(`Status: ${route.status ?? '(unknown)'}`);
|
|
164
|
+
console.log(`Active route: ${route.route_id === snapshot.activeRoute ? 'yes' : 'no'}`);
|
|
165
|
+
console.log(`Summary: ${route.summary ?? '(none)'}`);
|
|
166
|
+
console.log(`Why now: ${route.why_now ?? '(none)'}`);
|
|
167
|
+
console.log(`Next move: ${route.next_move ?? '(none)'}`);
|
|
168
|
+
if (Array.isArray(route.ticket_ids) && route.ticket_ids.length > 0) {
|
|
169
|
+
console.log(`Tickets: ${route.ticket_ids.join(', ')}`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function printTicketDetail(snapshot) {
|
|
174
|
+
const ticket = snapshot.ticketDetail;
|
|
175
|
+
console.log(`${snapshot.displayName} number-theory ticket ${snapshot.ticketId}`);
|
|
176
|
+
console.log(`Title: ${ticket.title ?? snapshot.ticketId}`);
|
|
177
|
+
console.log(`Status: ${ticket.status ?? '(unknown)'}`);
|
|
178
|
+
console.log(`Active ticket: ${ticket.ticket_id === snapshot.activeTicketDetail?.ticket_id ? 'yes' : 'no'}`);
|
|
179
|
+
console.log(`Summary: ${ticket.summary ?? '(none)'}`);
|
|
180
|
+
console.log(`Current blocker: ${ticket.current_blocker ?? '(none)'}`);
|
|
181
|
+
console.log(`Next move: ${ticket.next_move ?? '(none)'}`);
|
|
182
|
+
if (Array.isArray(ticket.atom_ids) && ticket.atom_ids.length > 0) {
|
|
183
|
+
console.log(`Atoms: ${ticket.atom_ids.join(', ')}`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function printAtomDetail(snapshot) {
|
|
188
|
+
const atom = snapshot.atomDetail;
|
|
189
|
+
console.log(`${snapshot.displayName} number-theory atom ${snapshot.atomId}`);
|
|
190
|
+
console.log(`Title: ${atom.title ?? snapshot.atomId}`);
|
|
191
|
+
console.log(`Status: ${atom.status ?? '(unknown)'}`);
|
|
192
|
+
console.log(`Current frontier atom: ${atom.atom_id === snapshot.firstReadyAtom?.atom_id ? 'yes' : 'no'}`);
|
|
193
|
+
console.log(`Summary: ${atom.summary ?? '(none)'}`);
|
|
194
|
+
console.log(`Next move: ${atom.next_move ?? '(none)'}`);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export function runNumberTheoryCommand(args) {
|
|
198
|
+
const [subcommand, ...rest] = args;
|
|
199
|
+
|
|
200
|
+
if (!subcommand || subcommand === 'help' || subcommand === '--help') {
|
|
201
|
+
console.log('Usage:');
|
|
202
|
+
console.log(' erdos number-theory status [<id>] [--json]');
|
|
203
|
+
console.log(' erdos number-theory frontier [<id>] [--json]');
|
|
204
|
+
console.log(' erdos number-theory routes [<id>] [--json]');
|
|
205
|
+
console.log(' erdos number-theory tickets [<id>] [--json]');
|
|
206
|
+
console.log(' erdos number-theory route <problem-id> <route-id> [--json]');
|
|
207
|
+
console.log(' erdos number-theory ticket <problem-id> <ticket-id> [--json]');
|
|
208
|
+
console.log(' erdos number-theory atom <problem-id> <atom-id> [--json]');
|
|
209
|
+
return 0;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (!['status', 'frontier', 'routes', 'tickets', 'route', 'ticket', 'atom'].includes(subcommand)) {
|
|
213
|
+
console.error(`Unknown number-theory subcommand: ${subcommand}`);
|
|
214
|
+
return 1;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const parsed = parseArgs(rest);
|
|
218
|
+
if (parsed.error) {
|
|
219
|
+
console.error(parsed.error);
|
|
220
|
+
return 1;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const { problem, error } = resolveNumberTheoryProblem(parsed.problemId);
|
|
224
|
+
if (error) {
|
|
225
|
+
console.error(error);
|
|
226
|
+
return 1;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (subcommand === 'route') {
|
|
230
|
+
if (!parsed.entityId) {
|
|
231
|
+
console.error('Missing route id.');
|
|
232
|
+
return 1;
|
|
233
|
+
}
|
|
234
|
+
const snapshot = getNumberTheoryRouteSnapshot(problem, parsed.entityId);
|
|
235
|
+
if (!snapshot) {
|
|
236
|
+
console.error(`Unknown number-theory route: ${parsed.entityId}`);
|
|
237
|
+
return 1;
|
|
238
|
+
}
|
|
239
|
+
if (parsed.asJson) {
|
|
240
|
+
console.log(JSON.stringify(snapshot, null, 2));
|
|
241
|
+
return 0;
|
|
242
|
+
}
|
|
243
|
+
printRouteDetail(snapshot);
|
|
244
|
+
return 0;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (subcommand === 'ticket') {
|
|
248
|
+
if (!parsed.entityId) {
|
|
249
|
+
console.error('Missing ticket id.');
|
|
250
|
+
return 1;
|
|
251
|
+
}
|
|
252
|
+
const snapshot = getNumberTheoryTicketSnapshot(problem, parsed.entityId);
|
|
253
|
+
if (!snapshot) {
|
|
254
|
+
console.error(`Unknown number-theory ticket: ${parsed.entityId}`);
|
|
255
|
+
return 1;
|
|
256
|
+
}
|
|
257
|
+
if (parsed.asJson) {
|
|
258
|
+
console.log(JSON.stringify(snapshot, null, 2));
|
|
259
|
+
return 0;
|
|
260
|
+
}
|
|
261
|
+
printTicketDetail(snapshot);
|
|
262
|
+
return 0;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (subcommand === 'atom') {
|
|
266
|
+
if (!parsed.entityId) {
|
|
267
|
+
console.error('Missing atom id.');
|
|
268
|
+
return 1;
|
|
269
|
+
}
|
|
270
|
+
const snapshot = getNumberTheoryAtomSnapshot(problem, parsed.entityId);
|
|
271
|
+
if (!snapshot) {
|
|
272
|
+
console.error(`Unknown number-theory atom: ${parsed.entityId}`);
|
|
273
|
+
return 1;
|
|
274
|
+
}
|
|
275
|
+
if (parsed.asJson) {
|
|
276
|
+
console.log(JSON.stringify(snapshot, null, 2));
|
|
277
|
+
return 0;
|
|
278
|
+
}
|
|
279
|
+
printAtomDetail(snapshot);
|
|
280
|
+
return 0;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const snapshot = buildNumberTheoryStatusSnapshot(problem);
|
|
284
|
+
if (parsed.asJson) {
|
|
285
|
+
console.log(JSON.stringify(snapshot, null, 2));
|
|
286
|
+
return 0;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (subcommand === 'frontier') {
|
|
290
|
+
printFrontier(snapshot);
|
|
291
|
+
return 0;
|
|
292
|
+
}
|
|
293
|
+
if (subcommand === 'routes') {
|
|
294
|
+
printRoutes(snapshot);
|
|
295
|
+
return 0;
|
|
296
|
+
}
|
|
297
|
+
if (subcommand === 'tickets') {
|
|
298
|
+
printTickets(snapshot);
|
|
299
|
+
return 0;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
printStatus(snapshot);
|
|
303
|
+
return 0;
|
|
304
|
+
}
|
package/src/commands/pull.js
CHANGED
|
@@ -45,7 +45,7 @@ function inferClusterFromUpstream(upstreamRecord) {
|
|
|
45
45
|
function parsePullArgs(args) {
|
|
46
46
|
const [kind, value, ...rest] = args;
|
|
47
47
|
if (!['problem', 'artifacts', 'literature'].includes(kind)) {
|
|
48
|
-
return { error: 'Usage: erdos pull problem|artifacts|literature <id> [--dest <path>] [--include-site] [--include-public-search] [--include-crossref] [--include-openalex] [--refresh-upstream]' };
|
|
48
|
+
return { error: 'Usage: erdos pull problem|artifacts|literature <id> [--dest <path>] [--include-site] [--include-public-search] [--include-crossref] [--include-openalex] [--refresh-upstream] [--json]' };
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
let destination = null;
|
|
@@ -54,6 +54,7 @@ function parsePullArgs(args) {
|
|
|
54
54
|
let includeCrossref = false;
|
|
55
55
|
let includeOpenAlex = false;
|
|
56
56
|
let refreshUpstream = false;
|
|
57
|
+
let asJson = false;
|
|
57
58
|
|
|
58
59
|
for (let index = 0; index < rest.length; index += 1) {
|
|
59
60
|
const token = rest[index];
|
|
@@ -85,6 +86,10 @@ function parsePullArgs(args) {
|
|
|
85
86
|
refreshUpstream = true;
|
|
86
87
|
continue;
|
|
87
88
|
}
|
|
89
|
+
if (token === '--json') {
|
|
90
|
+
asJson = true;
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
88
93
|
return { error: `Unknown pull option: ${token}` };
|
|
89
94
|
}
|
|
90
95
|
|
|
@@ -97,6 +102,7 @@ function parsePullArgs(args) {
|
|
|
97
102
|
includeCrossref,
|
|
98
103
|
includeOpenAlex,
|
|
99
104
|
refreshUpstream,
|
|
105
|
+
asJson,
|
|
100
106
|
};
|
|
101
107
|
}
|
|
102
108
|
|
|
@@ -530,9 +536,9 @@ export async function runPullCommand(args, options = {}) {
|
|
|
530
536
|
if (args.length === 0 || args[0] === 'help' || args[0] === '--help') {
|
|
531
537
|
if (!silent) {
|
|
532
538
|
console.log('Usage:');
|
|
533
|
-
console.log(' erdos pull problem <id> [--dest <path>] [--include-site] [--include-public-search] [--include-crossref] [--include-openalex] [--refresh-upstream]');
|
|
534
|
-
console.log(' erdos pull artifacts <id> [--dest <path>] [--refresh-upstream]');
|
|
535
|
-
console.log(' erdos pull literature <id> [--dest <path>] [--include-site] [--include-public-search] [--include-crossref] [--include-openalex] [--refresh-upstream]');
|
|
539
|
+
console.log(' erdos pull problem <id> [--dest <path>] [--include-site] [--include-public-search] [--include-crossref] [--include-openalex] [--refresh-upstream] [--json]');
|
|
540
|
+
console.log(' erdos pull artifacts <id> [--dest <path>] [--refresh-upstream] [--json]');
|
|
541
|
+
console.log(' erdos pull literature <id> [--dest <path>] [--include-site] [--include-public-search] [--include-crossref] [--include-openalex] [--refresh-upstream] [--json]');
|
|
536
542
|
}
|
|
537
543
|
return 0;
|
|
538
544
|
}
|
|
@@ -571,6 +577,17 @@ export async function runPullCommand(args, options = {}) {
|
|
|
571
577
|
? path.resolve(parsed.destination)
|
|
572
578
|
: getWorkspaceProblemArtifactDir(parsed.problemId);
|
|
573
579
|
const result = writeArtifactsLane(String(parsed.problemId), destination, localProblem, upstreamRecord, snapshot);
|
|
580
|
+
if (parsed.asJson) {
|
|
581
|
+
console.log(JSON.stringify({
|
|
582
|
+
kind: 'artifacts',
|
|
583
|
+
problemId: String(parsed.problemId),
|
|
584
|
+
destination,
|
|
585
|
+
localProblemIncluded: Boolean(localProblem),
|
|
586
|
+
upstreamRecordIncluded: Boolean(upstreamRecord),
|
|
587
|
+
artifactsCopied: result.copiedArtifacts?.length ?? result.artifactsCopied ?? 0,
|
|
588
|
+
}, null, 2));
|
|
589
|
+
return 0;
|
|
590
|
+
}
|
|
574
591
|
if (!silent) {
|
|
575
592
|
console.log(`Artifact bundle created: ${destination}`);
|
|
576
593
|
console.log(`Local canonical dossier included: ${localProblem ? 'yes' : 'no'}`);
|
|
@@ -594,6 +611,24 @@ export async function runPullCommand(args, options = {}) {
|
|
|
594
611
|
parsed.includeCrossref,
|
|
595
612
|
parsed.includeOpenAlex,
|
|
596
613
|
);
|
|
614
|
+
if (parsed.asJson) {
|
|
615
|
+
console.log(JSON.stringify({
|
|
616
|
+
kind: 'literature',
|
|
617
|
+
problemId: String(parsed.problemId),
|
|
618
|
+
destination,
|
|
619
|
+
localProblemIncluded: Boolean(localProblem),
|
|
620
|
+
upstreamRecordIncluded: Boolean(upstreamRecord),
|
|
621
|
+
includedSiteSnapshot: result.siteStatus.included,
|
|
622
|
+
siteStatusError: result.siteStatus.error,
|
|
623
|
+
includedPublicSearch: result.publicSearch.included,
|
|
624
|
+
publicSearchError: result.publicSearch.error,
|
|
625
|
+
includedCrossref: result.crossref.included,
|
|
626
|
+
crossrefError: result.crossref.error,
|
|
627
|
+
includedOpenAlex: result.openalex.included,
|
|
628
|
+
openAlexError: result.openalex.error,
|
|
629
|
+
}, null, 2));
|
|
630
|
+
return 0;
|
|
631
|
+
}
|
|
597
632
|
if (!silent) {
|
|
598
633
|
console.log(`Literature bundle created: ${destination}`);
|
|
599
634
|
console.log(`Local dossier context included: ${localProblem ? 'yes' : 'no'}`);
|
|
@@ -662,6 +697,23 @@ export async function runPullCommand(args, options = {}) {
|
|
|
662
697
|
openAlexError: literatureResult.openalex.error,
|
|
663
698
|
});
|
|
664
699
|
|
|
700
|
+
if (parsed.asJson) {
|
|
701
|
+
console.log(JSON.stringify({
|
|
702
|
+
kind: 'problem',
|
|
703
|
+
problemId: String(parsed.problemId),
|
|
704
|
+
destination: rootDestination,
|
|
705
|
+
artifactsDir: artifactDestination,
|
|
706
|
+
literatureDir: literatureDestination,
|
|
707
|
+
localProblemIncluded: Boolean(localProblem),
|
|
708
|
+
upstreamRecordIncluded: Boolean(upstreamRecord),
|
|
709
|
+
includedSiteSnapshot: literatureResult.siteStatus.included,
|
|
710
|
+
includedPublicSearch: literatureResult.publicSearch.included,
|
|
711
|
+
includedCrossref: literatureResult.crossref.included,
|
|
712
|
+
includedOpenAlex: literatureResult.openalex.included,
|
|
713
|
+
}, null, 2));
|
|
714
|
+
return 0;
|
|
715
|
+
}
|
|
716
|
+
|
|
665
717
|
if (!silent) {
|
|
666
718
|
console.log(`Pull bundle created: ${rootDestination}`);
|
|
667
719
|
console.log(`Artifact lane: ${artifactDestination}`);
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { getProblem } from '../atlas/catalog.js';
|
|
2
2
|
import { loadConfig } from '../runtime/config.js';
|
|
3
|
+
import { buildGraphTheoryStatusSnapshot } from '../runtime/graph-theory.js';
|
|
4
|
+
import { buildNumberTheoryStatusSnapshot } from '../runtime/number-theory.js';
|
|
3
5
|
import { buildSunflowerStatusSnapshot } from '../runtime/sunflower.js';
|
|
4
6
|
import { getWorkspaceSummary } from '../runtime/workspace.js';
|
|
5
7
|
|
|
6
8
|
export function runWorkspaceCommand(args) {
|
|
7
|
-
const [subcommand] = args;
|
|
9
|
+
const [subcommand, ...rest] = args;
|
|
8
10
|
|
|
9
11
|
if (!subcommand || subcommand === 'help' || subcommand === '--help') {
|
|
10
12
|
console.log('Usage:');
|
|
@@ -17,8 +19,30 @@ export function runWorkspaceCommand(args) {
|
|
|
17
19
|
return 1;
|
|
18
20
|
}
|
|
19
21
|
|
|
22
|
+
const asJson = rest.includes('--json');
|
|
23
|
+
|
|
20
24
|
const summary = getWorkspaceSummary();
|
|
21
25
|
const config = loadConfig();
|
|
26
|
+
if (asJson) {
|
|
27
|
+
const payload = {
|
|
28
|
+
...summary,
|
|
29
|
+
preferredAgent: config.preferredAgent,
|
|
30
|
+
};
|
|
31
|
+
if (summary.activeProblem) {
|
|
32
|
+
const problem = getProblem(summary.activeProblem);
|
|
33
|
+
if (problem?.cluster === 'sunflower') {
|
|
34
|
+
payload.sunflower = buildSunflowerStatusSnapshot(problem);
|
|
35
|
+
}
|
|
36
|
+
if (problem?.cluster === 'number-theory') {
|
|
37
|
+
payload.numberTheory = buildNumberTheoryStatusSnapshot(problem);
|
|
38
|
+
}
|
|
39
|
+
if (problem?.cluster === 'graph-theory') {
|
|
40
|
+
payload.graphTheory = buildGraphTheoryStatusSnapshot(problem);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
44
|
+
return 0;
|
|
45
|
+
}
|
|
22
46
|
console.log(`Workspace root: ${summary.workspaceRoot}`);
|
|
23
47
|
console.log(`State dir: ${summary.stateDir}`);
|
|
24
48
|
console.log(`Initialized: ${summary.hasState ? 'yes' : 'no'}`);
|
|
@@ -76,6 +100,36 @@ export function runWorkspaceCommand(args) {
|
|
|
76
100
|
}
|
|
77
101
|
console.log(`Sunflower compute next: ${sunflower.computeNextAction}`);
|
|
78
102
|
}
|
|
103
|
+
if (problem?.cluster === 'number-theory') {
|
|
104
|
+
const numberTheory = buildNumberTheoryStatusSnapshot(problem);
|
|
105
|
+
console.log(`Number-theory family role: ${numberTheory.familyRole ?? '(none)'}`);
|
|
106
|
+
console.log(`Number-theory harness profile: ${numberTheory.harnessProfile ?? '(none)'}`);
|
|
107
|
+
console.log(`Number-theory route: ${numberTheory.activeRoute ?? '(none)'}`);
|
|
108
|
+
console.log(`Number-theory frontier: ${numberTheory.frontierDetail ?? '(none)'}`);
|
|
109
|
+
console.log(`Number-theory frontier note: ${numberTheory.frontierNotePath ?? '(none)'}`);
|
|
110
|
+
console.log(`Number-theory route history: ${numberTheory.routeHistoryPath ?? '(none)'}`);
|
|
111
|
+
console.log(`Number-theory archive mode: ${numberTheory.archiveMode ?? '(none)'}`);
|
|
112
|
+
console.log(`Number-theory active ticket: ${numberTheory.activeTicketDetail?.ticket_id ?? '(none)'}`);
|
|
113
|
+
console.log(`Number-theory ready atoms: ${numberTheory.readyAtomCount}`);
|
|
114
|
+
if (numberTheory.firstReadyAtom) {
|
|
115
|
+
console.log(`Number-theory first ready atom: ${numberTheory.firstReadyAtom.atom_id} — ${numberTheory.firstReadyAtom.title}`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (problem?.cluster === 'graph-theory') {
|
|
119
|
+
const graphTheory = buildGraphTheoryStatusSnapshot(problem);
|
|
120
|
+
console.log(`Graph-theory family role: ${graphTheory.familyRole ?? '(none)'}`);
|
|
121
|
+
console.log(`Graph-theory harness profile: ${graphTheory.harnessProfile ?? '(none)'}`);
|
|
122
|
+
console.log(`Graph-theory route: ${graphTheory.activeRoute ?? '(none)'}`);
|
|
123
|
+
console.log(`Graph-theory frontier: ${graphTheory.frontierDetail ?? '(none)'}`);
|
|
124
|
+
console.log(`Graph-theory frontier note: ${graphTheory.frontierNotePath ?? '(none)'}`);
|
|
125
|
+
console.log(`Graph-theory route history: ${graphTheory.routeHistoryPath ?? '(none)'}`);
|
|
126
|
+
console.log(`Graph-theory archive mode: ${graphTheory.archiveMode ?? '(none)'}`);
|
|
127
|
+
console.log(`Graph-theory active ticket: ${graphTheory.activeTicketDetail?.ticket_id ?? '(none)'}`);
|
|
128
|
+
console.log(`Graph-theory ready atoms: ${graphTheory.readyAtomCount}`);
|
|
129
|
+
if (graphTheory.firstReadyAtom) {
|
|
130
|
+
console.log(`Graph-theory first ready atom: ${graphTheory.firstReadyAtom.atom_id} — ${graphTheory.firstReadyAtom.title}`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
79
133
|
}
|
|
80
134
|
return 0;
|
|
81
135
|
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { parse } from 'yaml';
|
|
4
|
+
import { getPackProblemDir } from './paths.js';
|
|
5
|
+
|
|
6
|
+
function readYamlIfPresent(filePath) {
|
|
7
|
+
if (!fs.existsSync(filePath)) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
return parse(fs.readFileSync(filePath, 'utf8'));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function getPackFile(problemId, fileName) {
|
|
14
|
+
return path.join(getPackProblemDir('graph-theory', problemId), fileName);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function normalizeQuestionLedger(rawLedger) {
|
|
18
|
+
return {
|
|
19
|
+
openQuestions: rawLedger?.open_questions ?? [],
|
|
20
|
+
activeRouteNotes: rawLedger?.active_route_notes ?? [],
|
|
21
|
+
routeBreakthroughs: rawLedger?.route_breakthroughs ?? [],
|
|
22
|
+
problemSolved: rawLedger?.problem_solved ?? [],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function parseOpsDetails(problemId) {
|
|
27
|
+
const opsDetailsPath = getPackFile(problemId, 'OPS_DETAILS.yaml');
|
|
28
|
+
const payload = readYamlIfPresent(opsDetailsPath);
|
|
29
|
+
if (!payload) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
packetId: payload.packet_id ?? null,
|
|
34
|
+
summary: payload.summary ?? null,
|
|
35
|
+
path: opsDetailsPath,
|
|
36
|
+
routes: payload.routes ?? [],
|
|
37
|
+
tickets: payload.tickets ?? [],
|
|
38
|
+
atoms: payload.atoms ?? [],
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function findRouteDetail(opsDetails, routeId) {
|
|
43
|
+
if (!opsDetails || !Array.isArray(opsDetails.routes)) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
return opsDetails.routes.find((route) => route.route_id === routeId) ?? null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function firstMatching(items, predicate) {
|
|
50
|
+
if (!Array.isArray(items)) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
return items.find(predicate) ?? items[0] ?? null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function resolveArchiveMode(problem) {
|
|
57
|
+
const siteStatus = String(problem.siteStatus ?? '').toLowerCase();
|
|
58
|
+
if (siteStatus === 'solved') {
|
|
59
|
+
return 'method_exemplar';
|
|
60
|
+
}
|
|
61
|
+
if (siteStatus === 'proved' || siteStatus === 'proved (lean)') {
|
|
62
|
+
return 'proof_archive';
|
|
63
|
+
}
|
|
64
|
+
if (siteStatus === 'decidable') {
|
|
65
|
+
return 'decision_archive';
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function solvedLikeSiteStatus(problem) {
|
|
71
|
+
const siteStatus = String(problem.siteStatus ?? '').toLowerCase();
|
|
72
|
+
return siteStatus === 'solved' || siteStatus === 'proved' || siteStatus === 'proved (lean)';
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function buildGraphTheoryStatusSnapshot(problem) {
|
|
76
|
+
const contextPath = getPackFile(problem.problemId, 'context.yaml');
|
|
77
|
+
const contextMarkdownPath = getPackFile(problem.problemId, 'CONTEXT.md');
|
|
78
|
+
const routePacketPath = getPackFile(problem.problemId, 'ROUTE_PACKET.yaml');
|
|
79
|
+
const frontierNotePath = getPackFile(problem.problemId, 'FRONTIER_NOTE.md');
|
|
80
|
+
const routeHistoryPath = getPackFile(problem.problemId, 'ROUTE_HISTORY.md');
|
|
81
|
+
const checkpointTemplatePath = getPackFile(problem.problemId, 'CHECKPOINT_TEMPLATE.md');
|
|
82
|
+
const reportTemplatePath = getPackFile(problem.problemId, 'REPORT_TEMPLATE.md');
|
|
83
|
+
|
|
84
|
+
const context = readYamlIfPresent(contextPath) ?? {};
|
|
85
|
+
const routePacket = readYamlIfPresent(routePacketPath);
|
|
86
|
+
const opsDetails = parseOpsDetails(problem.problemId);
|
|
87
|
+
|
|
88
|
+
const activeRoute =
|
|
89
|
+
problem.researchState?.active_route
|
|
90
|
+
?? context.default_active_route
|
|
91
|
+
?? routePacket?.route_id
|
|
92
|
+
?? null;
|
|
93
|
+
const archiveMode = resolveArchiveMode(problem);
|
|
94
|
+
const problemSolved = typeof problem.researchState?.problem_solved === 'boolean'
|
|
95
|
+
? problem.researchState.problem_solved
|
|
96
|
+
: solvedLikeSiteStatus(problem);
|
|
97
|
+
const openProblem = typeof problem.researchState?.open_problem === 'boolean'
|
|
98
|
+
? problem.researchState.open_problem
|
|
99
|
+
: String(problem.siteStatus ?? '').toLowerCase() === 'open';
|
|
100
|
+
const routeBreakthrough = typeof problem.researchState?.route_breakthrough === 'boolean'
|
|
101
|
+
? problem.researchState.route_breakthrough
|
|
102
|
+
: problemSolved;
|
|
103
|
+
|
|
104
|
+
const activeRouteDetail = findRouteDetail(opsDetails, activeRoute) ?? firstMatching(opsDetails?.routes, () => true);
|
|
105
|
+
const activeTicketDetail = firstMatching(
|
|
106
|
+
opsDetails?.tickets,
|
|
107
|
+
(ticket) => ticket.status === 'active' && (!activeRoute || ticket.route_id === activeRoute),
|
|
108
|
+
);
|
|
109
|
+
const firstReadyAtom = firstMatching(
|
|
110
|
+
opsDetails?.atoms,
|
|
111
|
+
(atom) => atom.status === 'ready' && (!activeRoute || atom.route_id === activeRoute),
|
|
112
|
+
);
|
|
113
|
+
const readyAtoms = Array.isArray(opsDetails?.atoms)
|
|
114
|
+
? opsDetails.atoms.filter((atom) => atom.status === 'ready')
|
|
115
|
+
: [];
|
|
116
|
+
|
|
117
|
+
return {
|
|
118
|
+
generatedAt: new Date().toISOString(),
|
|
119
|
+
problemId: problem.problemId,
|
|
120
|
+
displayName: problem.displayName,
|
|
121
|
+
title: problem.title,
|
|
122
|
+
cluster: problem.cluster,
|
|
123
|
+
familyRole: context.family_role ?? 'graph_theory_pack',
|
|
124
|
+
harnessProfile: context.harness_profile ?? 'starter_cockpit',
|
|
125
|
+
activeRoute,
|
|
126
|
+
routeBreakthrough,
|
|
127
|
+
problemSolved,
|
|
128
|
+
openProblem,
|
|
129
|
+
siteStatus: problem.siteStatus,
|
|
130
|
+
archiveMode,
|
|
131
|
+
bootstrapFocus: context.bootstrap_focus ?? null,
|
|
132
|
+
routeStory: context.route_story ?? routePacket?.frontier_claim ?? problem.shortStatement,
|
|
133
|
+
frontierLabel: context.frontier_label ?? activeRoute ?? 'graph_theory_frontier',
|
|
134
|
+
frontierDetail: firstReadyAtom?.summary ?? context.frontier_detail ?? activeRouteDetail?.summary ?? problem.shortStatement,
|
|
135
|
+
checkpointFocus: context.checkpoint_focus ?? activeRouteDetail?.why_now ?? null,
|
|
136
|
+
nextHonestMove:
|
|
137
|
+
firstReadyAtom?.next_move
|
|
138
|
+
?? activeTicketDetail?.next_move
|
|
139
|
+
?? context.next_honest_move
|
|
140
|
+
?? 'Freeze the current graph-theory packet without widening status claims.',
|
|
141
|
+
relatedCoreProblems: context.related_core_problems ?? [],
|
|
142
|
+
literatureFocus: context.literature_focus ?? [],
|
|
143
|
+
artifactFocus: context.artifact_focus ?? [],
|
|
144
|
+
questionLedger: normalizeQuestionLedger(context.question_ledger),
|
|
145
|
+
contextPresent: fs.existsSync(contextPath),
|
|
146
|
+
contextPath,
|
|
147
|
+
contextMarkdownPath,
|
|
148
|
+
routePacketPresent: Boolean(routePacket),
|
|
149
|
+
routePacket,
|
|
150
|
+
routePacketPath,
|
|
151
|
+
frontierNotePresent: fs.existsSync(frontierNotePath),
|
|
152
|
+
frontierNotePath,
|
|
153
|
+
routeHistoryPresent: fs.existsSync(routeHistoryPath),
|
|
154
|
+
routeHistoryPath,
|
|
155
|
+
checkpointTemplatePresent: fs.existsSync(checkpointTemplatePath),
|
|
156
|
+
checkpointTemplatePath,
|
|
157
|
+
reportTemplatePresent: fs.existsSync(reportTemplatePath),
|
|
158
|
+
reportTemplatePath,
|
|
159
|
+
opsDetailsPresent: Boolean(opsDetails),
|
|
160
|
+
opsDetailsPath: opsDetails?.path ?? getPackFile(problem.problemId, 'OPS_DETAILS.yaml'),
|
|
161
|
+
opsDetails,
|
|
162
|
+
activeRouteDetail,
|
|
163
|
+
activeTicketDetail,
|
|
164
|
+
firstReadyAtom,
|
|
165
|
+
readyAtomCount: readyAtoms.length,
|
|
166
|
+
};
|
|
167
|
+
}
|