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.
Files changed (62) hide show
  1. package/README.md +88 -3
  2. package/docs/RESEARCH_LOOP.md +7 -0
  3. package/package.json +1 -1
  4. package/packs/graph-theory/README.md +17 -0
  5. package/packs/graph-theory/problems/1008/CHECKPOINT_TEMPLATE.md +9 -0
  6. package/packs/graph-theory/problems/1008/CONTEXT.md +9 -0
  7. package/packs/graph-theory/problems/1008/FRONTIER_NOTE.md +8 -0
  8. package/packs/graph-theory/problems/1008/OPS_DETAILS.yaml +25 -0
  9. package/packs/graph-theory/problems/1008/REPORT_TEMPLATE.md +9 -0
  10. package/packs/graph-theory/problems/1008/ROUTE_HISTORY.md +5 -0
  11. package/packs/graph-theory/problems/1008/ROUTE_PACKET.yaml +13 -0
  12. package/packs/graph-theory/problems/1008/context.yaml +27 -0
  13. package/packs/graph-theory/problems/19/CHECKPOINT_TEMPLATE.md +9 -0
  14. package/packs/graph-theory/problems/19/CONTEXT.md +9 -0
  15. package/packs/graph-theory/problems/19/FRONTIER_NOTE.md +8 -0
  16. package/packs/graph-theory/problems/19/OPS_DETAILS.yaml +25 -0
  17. package/packs/graph-theory/problems/19/REPORT_TEMPLATE.md +9 -0
  18. package/packs/graph-theory/problems/19/ROUTE_HISTORY.md +5 -0
  19. package/packs/graph-theory/problems/19/ROUTE_PACKET.yaml +13 -0
  20. package/packs/graph-theory/problems/19/context.yaml +25 -0
  21. package/packs/graph-theory/problems/22/CHECKPOINT_TEMPLATE.md +9 -0
  22. package/packs/graph-theory/problems/22/CONTEXT.md +9 -0
  23. package/packs/graph-theory/problems/22/FRONTIER_NOTE.md +8 -0
  24. package/packs/graph-theory/problems/22/OPS_DETAILS.yaml +25 -0
  25. package/packs/graph-theory/problems/22/REPORT_TEMPLATE.md +9 -0
  26. package/packs/graph-theory/problems/22/ROUTE_HISTORY.md +5 -0
  27. package/packs/graph-theory/problems/22/ROUTE_PACKET.yaml +13 -0
  28. package/packs/graph-theory/problems/22/context.yaml +26 -0
  29. package/packs/number-theory/README.md +16 -9
  30. package/packs/number-theory/problems/1/CHECKPOINT_TEMPLATE.md +7 -0
  31. package/packs/number-theory/problems/1/FRONTIER_NOTE.md +8 -0
  32. package/packs/number-theory/problems/1/OPS_DETAILS.yaml +25 -0
  33. package/packs/number-theory/problems/1/REPORT_TEMPLATE.md +7 -0
  34. package/packs/number-theory/problems/1/ROUTE_HISTORY.md +5 -0
  35. package/packs/number-theory/problems/1/ROUTE_PACKET.yaml +13 -0
  36. package/packs/number-theory/problems/1/context.yaml +10 -10
  37. package/packs/number-theory/problems/2/CHECKPOINT_TEMPLATE.md +7 -0
  38. package/packs/number-theory/problems/2/FRONTIER_NOTE.md +8 -0
  39. package/packs/number-theory/problems/2/OPS_DETAILS.yaml +25 -0
  40. package/packs/number-theory/problems/2/REPORT_TEMPLATE.md +7 -0
  41. package/packs/number-theory/problems/2/ROUTE_HISTORY.md +5 -0
  42. package/packs/number-theory/problems/2/ROUTE_PACKET.yaml +13 -0
  43. package/packs/number-theory/problems/2/context.yaml +11 -11
  44. package/packs/sunflower/README.md +2 -2
  45. package/packs/sunflower/problems/536/CHECKPOINT_TEMPLATE.md +7 -0
  46. package/packs/sunflower/problems/536/FRONTIER_NOTE.md +8 -0
  47. package/packs/sunflower/problems/536/REPORT_TEMPLATE.md +7 -0
  48. package/packs/sunflower/problems/536/ROUTE_HISTORY.md +5 -0
  49. package/packs/sunflower/problems/856/CHECKPOINT_TEMPLATE.md +7 -0
  50. package/packs/sunflower/problems/856/FRONTIER_NOTE.md +8 -0
  51. package/packs/sunflower/problems/856/REPORT_TEMPLATE.md +7 -0
  52. package/packs/sunflower/problems/856/ROUTE_HISTORY.md +5 -0
  53. package/src/cli/index.js +25 -8
  54. package/src/commands/archive.js +10 -1
  55. package/src/commands/cluster.js +19 -1
  56. package/src/commands/graph-theory.js +180 -0
  57. package/src/commands/number-theory.js +304 -0
  58. package/src/commands/pull.js +56 -4
  59. package/src/commands/workspace.js +55 -1
  60. package/src/runtime/graph-theory.js +167 -0
  61. package/src/runtime/number-theory.js +229 -0
  62. package/src/runtime/state.js +62 -0
@@ -0,0 +1,229 @@
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('number-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 findTicketDetail(opsDetails, ticketId) {
50
+ if (!opsDetails || !Array.isArray(opsDetails.tickets)) {
51
+ return null;
52
+ }
53
+ return opsDetails.tickets.find((ticket) => ticket.ticket_id === ticketId) ?? null;
54
+ }
55
+
56
+ function findAtomDetail(opsDetails, atomId) {
57
+ if (!opsDetails || !Array.isArray(opsDetails.atoms)) {
58
+ return null;
59
+ }
60
+ return opsDetails.atoms.find((atom) => atom.atom_id === atomId) ?? null;
61
+ }
62
+
63
+ function findActiveRouteDetail(opsDetails, activeRoute) {
64
+ if (!opsDetails || !Array.isArray(opsDetails.routes)) {
65
+ return null;
66
+ }
67
+ return opsDetails.routes.find((route) => route.route_id === activeRoute) ?? opsDetails.routes[0] ?? null;
68
+ }
69
+
70
+ function findActiveTicketDetail(opsDetails, activeRoute) {
71
+ if (!opsDetails || !Array.isArray(opsDetails.tickets)) {
72
+ return null;
73
+ }
74
+ return (
75
+ opsDetails.tickets.find((ticket) => ticket.status === 'active' && (!activeRoute || ticket.route_id === activeRoute))
76
+ ?? opsDetails.tickets.find((ticket) => !activeRoute || ticket.route_id === activeRoute)
77
+ ?? opsDetails.tickets[0]
78
+ ?? null
79
+ );
80
+ }
81
+
82
+ function findFirstReadyAtom(opsDetails, activeRoute) {
83
+ if (!opsDetails || !Array.isArray(opsDetails.atoms)) {
84
+ return null;
85
+ }
86
+ return (
87
+ opsDetails.atoms.find((atom) => atom.status === 'ready' && (!activeRoute || atom.route_id === activeRoute))
88
+ ?? opsDetails.atoms.find((atom) => atom.status === 'ready')
89
+ ?? null
90
+ );
91
+ }
92
+
93
+ function resolveArchiveMode(problem) {
94
+ const siteStatus = String(problem.siteStatus ?? '').toLowerCase();
95
+ if (siteStatus === 'solved') {
96
+ return 'method_exemplar';
97
+ }
98
+ if (siteStatus === 'disproved') {
99
+ return 'counterexample_archive';
100
+ }
101
+ return null;
102
+ }
103
+
104
+ export function buildNumberTheoryStatusSnapshot(problem) {
105
+ const contextPath = getPackFile(problem.problemId, 'context.yaml');
106
+ const contextMarkdownPath = getPackFile(problem.problemId, 'CONTEXT.md');
107
+ const routePacketPath = getPackFile(problem.problemId, 'ROUTE_PACKET.yaml');
108
+ const frontierNotePath = getPackFile(problem.problemId, 'FRONTIER_NOTE.md');
109
+ const routeHistoryPath = getPackFile(problem.problemId, 'ROUTE_HISTORY.md');
110
+ const checkpointTemplatePath = getPackFile(problem.problemId, 'CHECKPOINT_TEMPLATE.md');
111
+ const reportTemplatePath = getPackFile(problem.problemId, 'REPORT_TEMPLATE.md');
112
+
113
+ const context = readYamlIfPresent(contextPath) ?? {};
114
+ const routePacket = readYamlIfPresent(routePacketPath);
115
+ const opsDetails = parseOpsDetails(problem.problemId);
116
+
117
+ const activeRoute =
118
+ problem.researchState?.active_route
119
+ ?? context.default_active_route
120
+ ?? routePacket?.route_id
121
+ ?? null;
122
+ const routeBreakthrough = typeof problem.researchState?.route_breakthrough === 'boolean'
123
+ ? problem.researchState.route_breakthrough
124
+ : false;
125
+ const archiveMode = resolveArchiveMode(problem);
126
+ const problemSolved = typeof problem.researchState?.problem_solved === 'boolean'
127
+ ? problem.researchState.problem_solved
128
+ : String(problem.siteStatus ?? '').toLowerCase() === 'solved';
129
+ const openProblem = typeof problem.researchState?.open_problem === 'boolean'
130
+ ? problem.researchState.open_problem
131
+ : String(problem.siteStatus ?? '').toLowerCase() === 'open';
132
+
133
+ const activeRouteDetail = findActiveRouteDetail(opsDetails, activeRoute);
134
+ const activeTicketDetail = findActiveTicketDetail(opsDetails, activeRoute);
135
+ const firstReadyAtom = findFirstReadyAtom(opsDetails, activeRoute);
136
+ const readyAtoms = Array.isArray(opsDetails?.atoms)
137
+ ? opsDetails.atoms.filter((atom) => atom.status === 'ready')
138
+ : [];
139
+
140
+ return {
141
+ generatedAt: new Date().toISOString(),
142
+ problemId: problem.problemId,
143
+ displayName: problem.displayName,
144
+ title: problem.title,
145
+ cluster: problem.cluster,
146
+ familyRole: context.family_role ?? 'number_theory_pack',
147
+ harnessProfile: context.harness_profile ?? 'starter_cockpit',
148
+ activeRoute,
149
+ routeBreakthrough,
150
+ problemSolved,
151
+ openProblem,
152
+ siteStatus: problem.siteStatus,
153
+ archiveMode,
154
+ bootstrapFocus: context.bootstrap_focus ?? null,
155
+ routeStory: context.route_story ?? routePacket?.frontier_claim ?? problem.shortStatement,
156
+ frontierLabel: context.frontier_label ?? activeRoute ?? 'number_theory_frontier',
157
+ frontierDetail: firstReadyAtom?.summary ?? context.frontier_detail ?? activeRouteDetail?.summary ?? problem.shortStatement,
158
+ checkpointFocus: context.checkpoint_focus ?? activeRouteDetail?.why_now ?? null,
159
+ nextHonestMove:
160
+ firstReadyAtom?.next_move
161
+ ?? activeTicketDetail?.next_move
162
+ ?? context.next_honest_move
163
+ ?? 'Pull the dossier, freeze the route note, and preserve public-status honesty.',
164
+ relatedCoreProblems: context.related_core_problems ?? [],
165
+ literatureFocus: context.literature_focus ?? [],
166
+ artifactFocus: context.artifact_focus ?? [],
167
+ questionLedger: normalizeQuestionLedger(context.question_ledger),
168
+ contextPresent: fs.existsSync(contextPath),
169
+ contextPath,
170
+ contextMarkdownPath,
171
+ routePacketPresent: Boolean(routePacket),
172
+ routePacket,
173
+ routePacketPath,
174
+ frontierNotePresent: fs.existsSync(frontierNotePath),
175
+ frontierNotePath,
176
+ routeHistoryPresent: fs.existsSync(routeHistoryPath),
177
+ routeHistoryPath,
178
+ checkpointTemplatePresent: fs.existsSync(checkpointTemplatePath),
179
+ checkpointTemplatePath,
180
+ reportTemplatePresent: fs.existsSync(reportTemplatePath),
181
+ reportTemplatePath,
182
+ opsDetailsPresent: Boolean(opsDetails),
183
+ opsDetailsPath: opsDetails?.path ?? getPackFile(problem.problemId, 'OPS_DETAILS.yaml'),
184
+ opsDetails,
185
+ activeRouteDetail,
186
+ activeTicketDetail,
187
+ firstReadyAtom,
188
+ readyAtomCount: readyAtoms.length,
189
+ };
190
+ }
191
+
192
+ export function getNumberTheoryRouteSnapshot(problem, routeId) {
193
+ const snapshot = buildNumberTheoryStatusSnapshot(problem);
194
+ const routeDetail = findRouteDetail(snapshot.opsDetails, routeId);
195
+ if (!routeDetail) {
196
+ return null;
197
+ }
198
+ return {
199
+ ...snapshot,
200
+ routeId,
201
+ routeDetail,
202
+ };
203
+ }
204
+
205
+ export function getNumberTheoryTicketSnapshot(problem, ticketId) {
206
+ const snapshot = buildNumberTheoryStatusSnapshot(problem);
207
+ const ticketDetail = findTicketDetail(snapshot.opsDetails, ticketId);
208
+ if (!ticketDetail) {
209
+ return null;
210
+ }
211
+ return {
212
+ ...snapshot,
213
+ ticketId,
214
+ ticketDetail,
215
+ };
216
+ }
217
+
218
+ export function getNumberTheoryAtomSnapshot(problem, atomId) {
219
+ const snapshot = buildNumberTheoryStatusSnapshot(problem);
220
+ const atomDetail = findAtomDetail(snapshot.opsDetails, atomId);
221
+ if (!atomDetail) {
222
+ return null;
223
+ }
224
+ return {
225
+ ...snapshot,
226
+ atomId,
227
+ atomDetail,
228
+ };
229
+ }
@@ -1,12 +1,14 @@
1
1
  import { getProblem } from '../atlas/catalog.js';
2
2
  import { ensureConfig, loadConfig } from './config.js';
3
3
  import { fileExists, readJson, writeJson, writeText } from './files.js';
4
+ import { buildGraphTheoryStatusSnapshot } from './graph-theory.js';
4
5
  import {
5
6
  getWorkspaceQuestionLedgerPath,
6
7
  getWorkspaceRoot,
7
8
  getWorkspaceStateMarkdownPath,
8
9
  getWorkspaceStatePath,
9
10
  } from './paths.js';
11
+ import { buildNumberTheoryStatusSnapshot } from './number-theory.js';
10
12
  import { buildSunflowerStatusSnapshot } from './sunflower.js';
11
13
  import { readCurrentProblem } from './workspace.js';
12
14
  import { continuationDisplay, resolveContinuation } from './continuation.js';
@@ -218,6 +220,66 @@ function deriveProblemSummary(problem) {
218
220
  };
219
221
  }
220
222
 
223
+ if (problem.cluster === 'number-theory') {
224
+ const snapshot = buildNumberTheoryStatusSnapshot(problem);
225
+ return {
226
+ familyRole: snapshot.familyRole,
227
+ harnessProfile: snapshot.harnessProfile,
228
+ activeRoute: snapshot.activeRoute,
229
+ routeBreakthrough: snapshot.routeBreakthrough,
230
+ problemSolved: snapshot.problemSolved,
231
+ openProblem: snapshot.openProblem,
232
+ currentFrontier: {
233
+ kind: snapshot.firstReadyAtom ? 'ready_atom' : 'route_frontier',
234
+ detail: snapshot.firstReadyAtom
235
+ ? `${snapshot.firstReadyAtom.atom_id} — ${snapshot.firstReadyAtom.title}`
236
+ : snapshot.frontierDetail,
237
+ },
238
+ routeStory: snapshot.activeRouteDetail?.summary || snapshot.routeStory,
239
+ checkpointFocus: snapshot.checkpointFocus,
240
+ nextHonestMove: snapshot.nextHonestMove,
241
+ packArtifacts: {
242
+ frontierNotePath: snapshot.frontierNotePath,
243
+ routeHistoryPath: snapshot.routeHistoryPath,
244
+ checkpointTemplatePath: snapshot.checkpointTemplatePath,
245
+ reportTemplatePath: snapshot.reportTemplatePath,
246
+ },
247
+ activeTicketId: snapshot.activeTicketDetail?.ticket_id ?? null,
248
+ activeAtomId: snapshot.firstReadyAtom?.atom_id ?? null,
249
+ questionLedger: snapshot.questionLedger,
250
+ };
251
+ }
252
+
253
+ if (problem.cluster === 'graph-theory') {
254
+ const snapshot = buildGraphTheoryStatusSnapshot(problem);
255
+ return {
256
+ familyRole: snapshot.familyRole,
257
+ harnessProfile: snapshot.harnessProfile,
258
+ activeRoute: snapshot.activeRoute,
259
+ routeBreakthrough: snapshot.routeBreakthrough,
260
+ problemSolved: snapshot.problemSolved,
261
+ openProblem: snapshot.openProblem,
262
+ currentFrontier: {
263
+ kind: snapshot.firstReadyAtom ? 'ready_atom' : 'route_frontier',
264
+ detail: snapshot.firstReadyAtom
265
+ ? `${snapshot.firstReadyAtom.atom_id} — ${snapshot.firstReadyAtom.title}`
266
+ : snapshot.frontierDetail,
267
+ },
268
+ routeStory: snapshot.activeRouteDetail?.summary || snapshot.routeStory,
269
+ checkpointFocus: snapshot.checkpointFocus,
270
+ nextHonestMove: snapshot.nextHonestMove,
271
+ packArtifacts: {
272
+ frontierNotePath: snapshot.frontierNotePath,
273
+ routeHistoryPath: snapshot.routeHistoryPath,
274
+ checkpointTemplatePath: snapshot.checkpointTemplatePath,
275
+ reportTemplatePath: snapshot.reportTemplatePath,
276
+ },
277
+ activeTicketId: snapshot.activeTicketDetail?.ticket_id ?? null,
278
+ activeAtomId: snapshot.firstReadyAtom?.atom_id ?? null,
279
+ questionLedger: snapshot.questionLedger,
280
+ };
281
+ }
282
+
221
283
  return deriveGenericProblemSummary(problem);
222
284
  }
223
285