erdos-problems 0.1.6 → 0.1.8

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 (104) hide show
  1. package/README.md +47 -6
  2. package/docs/RESEARCH_LOOP.md +16 -0
  3. package/package.json +1 -1
  4. package/packs/sunflower/README.md +4 -0
  5. package/packs/sunflower/problems/20/AGENT_START.md +18 -0
  6. package/packs/sunflower/problems/20/CHECKPOINT_PACKET.md +11 -0
  7. package/packs/sunflower/problems/20/REPORT_PACKET.md +10 -0
  8. package/packs/sunflower/problems/20/ROUTE_PACKET.yaml +12 -0
  9. package/packs/sunflower/problems/857/AGENT_START.md +18 -0
  10. package/packs/sunflower/problems/857/CHECKPOINT_PACKET.md +11 -0
  11. package/packs/sunflower/problems/857/REPORT_PACKET.md +10 -0
  12. package/packs/sunflower/problems/857/ROUTE_PACKET.yaml +12 -0
  13. package/problems/1/AGENT_START.md +17 -0
  14. package/problems/1/CHECKPOINT_NOTES.md +11 -0
  15. package/problems/1/EVIDENCE.md +10 -0
  16. package/problems/1/FORMALIZATION.md +8 -0
  17. package/problems/1/REFERENCES.md +9 -0
  18. package/problems/1/ROUTES.md +14 -0
  19. package/problems/1/STATEMENT.md +21 -0
  20. package/problems/1/problem.yaml +44 -0
  21. package/problems/19/AGENT_START.md +17 -0
  22. package/problems/19/CHECKPOINT_NOTES.md +11 -0
  23. package/problems/19/EVIDENCE.md +10 -0
  24. package/problems/19/FORMALIZATION.md +8 -0
  25. package/problems/19/REFERENCES.md +9 -0
  26. package/problems/19/ROUTES.md +14 -0
  27. package/problems/19/STATEMENT.md +15 -0
  28. package/problems/19/problem.yaml +42 -0
  29. package/problems/2/AGENT_START.md +17 -0
  30. package/problems/2/CHECKPOINT_NOTES.md +11 -0
  31. package/problems/2/EVIDENCE.md +10 -0
  32. package/problems/2/FORMALIZATION.md +8 -0
  33. package/problems/2/REFERENCES.md +9 -0
  34. package/problems/2/ROUTES.md +14 -0
  35. package/problems/2/STATEMENT.md +15 -0
  36. package/problems/2/problem.yaml +42 -0
  37. package/problems/21/AGENT_START.md +17 -0
  38. package/problems/21/CHECKPOINT_NOTES.md +11 -0
  39. package/problems/21/EVIDENCE.md +10 -0
  40. package/problems/21/FORMALIZATION.md +8 -0
  41. package/problems/21/REFERENCES.md +9 -0
  42. package/problems/21/ROUTES.md +14 -0
  43. package/problems/21/STATEMENT.md +21 -0
  44. package/problems/21/problem.yaml +46 -0
  45. package/problems/22/AGENT_START.md +17 -0
  46. package/problems/22/CHECKPOINT_NOTES.md +11 -0
  47. package/problems/22/EVIDENCE.md +10 -0
  48. package/problems/22/FORMALIZATION.md +8 -0
  49. package/problems/22/REFERENCES.md +9 -0
  50. package/problems/22/ROUTES.md +14 -0
  51. package/problems/22/STATEMENT.md +21 -0
  52. package/problems/22/problem.yaml +44 -0
  53. package/problems/3/AGENT_START.md +17 -0
  54. package/problems/3/CHECKPOINT_NOTES.md +11 -0
  55. package/problems/3/EVIDENCE.md +10 -0
  56. package/problems/3/FORMALIZATION.md +8 -0
  57. package/problems/3/REFERENCES.md +9 -0
  58. package/problems/3/ROUTES.md +14 -0
  59. package/problems/3/STATEMENT.md +21 -0
  60. package/problems/3/problem.yaml +44 -0
  61. package/problems/4/AGENT_START.md +17 -0
  62. package/problems/4/CHECKPOINT_NOTES.md +11 -0
  63. package/problems/4/EVIDENCE.md +10 -0
  64. package/problems/4/FORMALIZATION.md +8 -0
  65. package/problems/4/REFERENCES.md +9 -0
  66. package/problems/4/ROUTES.md +14 -0
  67. package/problems/4/STATEMENT.md +21 -0
  68. package/problems/4/problem.yaml +44 -0
  69. package/problems/5/AGENT_START.md +17 -0
  70. package/problems/5/CHECKPOINT_NOTES.md +11 -0
  71. package/problems/5/EVIDENCE.md +10 -0
  72. package/problems/5/FORMALIZATION.md +8 -0
  73. package/problems/5/REFERENCES.md +9 -0
  74. package/problems/5/ROUTES.md +14 -0
  75. package/problems/5/STATEMENT.md +21 -0
  76. package/problems/5/problem.yaml +43 -0
  77. package/problems/6/AGENT_START.md +17 -0
  78. package/problems/6/CHECKPOINT_NOTES.md +11 -0
  79. package/problems/6/EVIDENCE.md +10 -0
  80. package/problems/6/FORMALIZATION.md +8 -0
  81. package/problems/6/REFERENCES.md +9 -0
  82. package/problems/6/ROUTES.md +14 -0
  83. package/problems/6/STATEMENT.md +21 -0
  84. package/problems/6/problem.yaml +43 -0
  85. package/problems/7/AGENT_START.md +17 -0
  86. package/problems/7/CHECKPOINT_NOTES.md +11 -0
  87. package/problems/7/EVIDENCE.md +10 -0
  88. package/problems/7/FORMALIZATION.md +8 -0
  89. package/problems/7/REFERENCES.md +9 -0
  90. package/problems/7/ROUTES.md +14 -0
  91. package/problems/7/STATEMENT.md +21 -0
  92. package/problems/7/problem.yaml +42 -0
  93. package/src/atlas/catalog.js +37 -29
  94. package/src/cli/index.js +4 -0
  95. package/src/commands/problem.js +6 -0
  96. package/src/commands/pull.js +72 -27
  97. package/src/commands/seed.js +264 -0
  98. package/src/commands/sunflower.js +10 -0
  99. package/src/commands/workspace.js +2 -0
  100. package/src/runtime/maintainer-seed.js +158 -8
  101. package/src/runtime/paths.js +8 -0
  102. package/src/runtime/problem-artifacts.js +36 -1
  103. package/src/runtime/sunflower.js +48 -0
  104. package/src/runtime/workspace.js +4 -0
@@ -10,6 +10,36 @@ import { getProblemArtifactInventory, scaffoldProblem } from '../runtime/problem
10
10
  import { loadActiveUpstreamSnapshot, syncUpstream } from '../upstream/sync.js';
11
11
  import { fetchProblemSiteSnapshot } from '../upstream/site.js';
12
12
 
13
+ function normalizeClusterLabel(rawTag) {
14
+ return String(rawTag ?? '')
15
+ .trim()
16
+ .toLowerCase()
17
+ .replace(/[^a-z0-9]+/g, '-')
18
+ .replace(/^-+|-+$/g, '');
19
+ }
20
+
21
+ function inferClusterFromUpstream(upstreamRecord) {
22
+ const normalized = Array.isArray(upstreamRecord?.tags)
23
+ ? upstreamRecord.tags.map(normalizeClusterLabel).filter(Boolean)
24
+ : [];
25
+ if (normalized.includes('number-theory')) {
26
+ return 'number-theory';
27
+ }
28
+ if (normalized.includes('graph-theory') || normalized.includes('chromatic-number')) {
29
+ return 'graph-theory';
30
+ }
31
+ if (normalized.includes('geometry')) {
32
+ return 'geometry';
33
+ }
34
+ if (normalized.includes('analysis')) {
35
+ return 'analysis';
36
+ }
37
+ if (normalized.includes('combinatorics') || normalized.includes('intersecting-family')) {
38
+ return 'combinatorics';
39
+ }
40
+ return null;
41
+ }
42
+
13
43
  function parsePullArgs(args) {
14
44
  const [kind, value, ...rest] = args;
15
45
  if (!['problem', 'artifacts', 'literature'].includes(kind)) {
@@ -55,7 +85,7 @@ function buildProblemRecord(problemId, localProblem, upstreamRecord) {
55
85
  generatedAt: new Date().toISOString(),
56
86
  problemId: String(problemId),
57
87
  title: localProblem?.title ?? `Erdos Problem #${problemId}`,
58
- cluster: localProblem?.cluster ?? null,
88
+ cluster: localProblem?.cluster ?? inferClusterFromUpstream(upstreamRecord),
59
89
  siteStatus: localProblem?.siteStatus ?? upstreamRecord?.status?.state ?? 'unknown',
60
90
  repoStatus: localProblem?.repoStatus ?? 'upstream-only',
61
91
  harnessDepth: localProblem?.harnessDepth ?? 'unseeded',
@@ -257,22 +287,29 @@ function writeRootProblemBundle(rootDir, problemId, localProblem, upstreamRecord
257
287
  return problemRecord;
258
288
  }
259
289
 
260
- export async function runPullCommand(args) {
290
+ export async function runPullCommand(args, options = {}) {
291
+ const silent = options.silent === true;
261
292
  if (args.length === 0 || args[0] === 'help' || args[0] === '--help') {
262
- console.log('Usage:');
263
- console.log(' erdos pull problem <id> [--dest <path>] [--include-site] [--refresh-upstream]');
264
- console.log(' erdos pull artifacts <id> [--dest <path>] [--refresh-upstream]');
265
- console.log(' erdos pull literature <id> [--dest <path>] [--include-site] [--refresh-upstream]');
293
+ if (!silent) {
294
+ console.log('Usage:');
295
+ console.log(' erdos pull problem <id> [--dest <path>] [--include-site] [--refresh-upstream]');
296
+ console.log(' erdos pull artifacts <id> [--dest <path>] [--refresh-upstream]');
297
+ console.log(' erdos pull literature <id> [--dest <path>] [--include-site] [--refresh-upstream]');
298
+ }
266
299
  return 0;
267
300
  }
268
301
 
269
302
  const parsed = parsePullArgs(args);
270
303
  if (parsed.error) {
271
- console.error(parsed.error);
304
+ if (!silent) {
305
+ console.error(parsed.error);
306
+ }
272
307
  return 1;
273
308
  }
274
309
  if (!parsed.problemId) {
275
- console.error('Missing problem id.');
310
+ if (!silent) {
311
+ console.error('Missing problem id.');
312
+ }
276
313
  return 1;
277
314
  }
278
315
 
@@ -285,7 +322,9 @@ export async function runPullCommand(args) {
285
322
  const upstreamRecord = snapshot?.index?.by_number?.[String(parsed.problemId)] ?? null;
286
323
 
287
324
  if (!localProblem && !upstreamRecord) {
288
- console.error(`Problem ${parsed.problemId} is not present in the local dossier set or upstream snapshot.`);
325
+ if (!silent) {
326
+ console.error(`Problem ${parsed.problemId} is not present in the local dossier set or upstream snapshot.`);
327
+ }
289
328
  return 1;
290
329
  }
291
330
 
@@ -294,10 +333,12 @@ export async function runPullCommand(args) {
294
333
  ? path.resolve(parsed.destination)
295
334
  : getWorkspaceProblemArtifactDir(parsed.problemId);
296
335
  const result = writeArtifactsLane(String(parsed.problemId), destination, localProblem, upstreamRecord, snapshot);
297
- console.log(`Artifact bundle created: ${destination}`);
298
- console.log(`Local canonical dossier included: ${localProblem ? 'yes' : 'no'}`);
299
- console.log(`Upstream record included: ${upstreamRecord ? 'yes' : 'no'}`);
300
- console.log(`Artifacts copied: ${result.copiedArtifacts?.length ?? result.artifactsCopied ?? 0}`);
336
+ if (!silent) {
337
+ console.log(`Artifact bundle created: ${destination}`);
338
+ console.log(`Local canonical dossier included: ${localProblem ? 'yes' : 'no'}`);
339
+ console.log(`Upstream record included: ${upstreamRecord ? 'yes' : 'no'}`);
340
+ console.log(`Artifacts copied: ${result.copiedArtifacts?.length ?? result.artifactsCopied ?? 0}`);
341
+ }
301
342
  return 0;
302
343
  }
303
344
 
@@ -306,12 +347,14 @@ export async function runPullCommand(args) {
306
347
  ? path.resolve(parsed.destination)
307
348
  : getWorkspaceProblemLiteratureDir(parsed.problemId);
308
349
  const result = await writeLiteratureLane(String(parsed.problemId), destination, localProblem, upstreamRecord, parsed.includeSite);
309
- console.log(`Literature bundle created: ${destination}`);
310
- console.log(`Local dossier context included: ${localProblem ? 'yes' : 'no'}`);
311
- console.log(`Upstream record included: ${upstreamRecord ? 'yes' : 'no'}`);
312
- console.log(`Live site snapshot included: ${result.siteStatus.included ? 'yes' : 'no'}`);
313
- if (result.siteStatus.error) {
314
- console.log(`Live site snapshot note: ${result.siteStatus.error}`);
350
+ if (!silent) {
351
+ console.log(`Literature bundle created: ${destination}`);
352
+ console.log(`Local dossier context included: ${localProblem ? 'yes' : 'no'}`);
353
+ console.log(`Upstream record included: ${upstreamRecord ? 'yes' : 'no'}`);
354
+ console.log(`Live site snapshot included: ${result.siteStatus.included ? 'yes' : 'no'}`);
355
+ if (result.siteStatus.error) {
356
+ console.log(`Live site snapshot note: ${result.siteStatus.error}`);
357
+ }
315
358
  }
316
359
  return 0;
317
360
  }
@@ -341,14 +384,16 @@ export async function runPullCommand(args) {
341
384
  siteSnapshotError: literatureResult.siteStatus.error,
342
385
  });
343
386
 
344
- console.log(`Pull bundle created: ${rootDestination}`);
345
- console.log(`Artifact lane: ${artifactDestination}`);
346
- console.log(`Literature lane: ${literatureDestination}`);
347
- console.log(`Local canonical dossier included: ${localProblem ? 'yes' : 'no'}`);
348
- console.log(`Upstream record included: ${upstreamRecord ? 'yes' : 'no'}`);
349
- console.log(`Live site snapshot included: ${literatureResult.siteStatus.included ? 'yes' : 'no'}`);
350
- if (literatureResult.siteStatus.error) {
351
- console.log(`Live site snapshot note: ${literatureResult.siteStatus.error}`);
387
+ if (!silent) {
388
+ console.log(`Pull bundle created: ${rootDestination}`);
389
+ console.log(`Artifact lane: ${artifactDestination}`);
390
+ console.log(`Literature lane: ${literatureDestination}`);
391
+ console.log(`Local canonical dossier included: ${localProblem ? 'yes' : 'no'}`);
392
+ console.log(`Upstream record included: ${upstreamRecord ? 'yes' : 'no'}`);
393
+ console.log(`Live site snapshot included: ${literatureResult.siteStatus.included ? 'yes' : 'no'}`);
394
+ if (literatureResult.siteStatus.error) {
395
+ console.log(`Live site snapshot note: ${literatureResult.siteStatus.error}`);
396
+ }
352
397
  }
353
398
  return 0;
354
399
  }
@@ -0,0 +1,264 @@
1
+ import path from 'node:path';
2
+ import { getProblem } from '../atlas/catalog.js';
3
+ import { syncCheckpoints } from '../runtime/checkpoints.js';
4
+ import { seedProblemFromPullBundle } from '../runtime/maintainer-seed.js';
5
+ import { getWorkspaceProblemPullDir, getWorkspaceRoot, getWorkspaceSeededProblemsDir } from '../runtime/paths.js';
6
+ import { syncState } from '../runtime/state.js';
7
+ import { readCurrentProblem, setCurrentProblem } from '../runtime/workspace.js';
8
+ import { runPullCommand } from './pull.js';
9
+
10
+ function parseSeedArgs(args) {
11
+ const [kind, value, ...rest] = args;
12
+ if (kind !== 'problem') {
13
+ return { error: 'Only `erdos seed problem <id>` is supported right now.' };
14
+ }
15
+
16
+ const parsed = {
17
+ problemId: value,
18
+ includeSite: false,
19
+ refreshUpstream: false,
20
+ cluster: null,
21
+ repoStatus: 'local_seeded',
22
+ harnessDepth: 'dossier',
23
+ title: null,
24
+ familyTags: [],
25
+ relatedProblems: [],
26
+ formalizationStatus: 'planned',
27
+ activeRoute: null,
28
+ routeBreakthrough: false,
29
+ problemSolved: false,
30
+ destRoot: null,
31
+ noActivate: false,
32
+ noLoopSync: false,
33
+ force: false,
34
+ asJson: false,
35
+ };
36
+
37
+ for (let index = 0; index < rest.length; index += 1) {
38
+ const token = rest[index];
39
+ if (token === '--include-site') {
40
+ parsed.includeSite = true;
41
+ continue;
42
+ }
43
+ if (token === '--refresh-upstream') {
44
+ parsed.refreshUpstream = true;
45
+ continue;
46
+ }
47
+ if (token === '--cluster') {
48
+ parsed.cluster = rest[index + 1];
49
+ if (!parsed.cluster) {
50
+ return { error: 'Missing cluster value after --cluster.' };
51
+ }
52
+ index += 1;
53
+ continue;
54
+ }
55
+ if (token === '--repo-status') {
56
+ parsed.repoStatus = rest[index + 1];
57
+ if (!parsed.repoStatus) {
58
+ return { error: 'Missing repo status after --repo-status.' };
59
+ }
60
+ index += 1;
61
+ continue;
62
+ }
63
+ if (token === '--harness-depth') {
64
+ parsed.harnessDepth = rest[index + 1];
65
+ if (!parsed.harnessDepth) {
66
+ return { error: 'Missing harness depth after --harness-depth.' };
67
+ }
68
+ index += 1;
69
+ continue;
70
+ }
71
+ if (token === '--title') {
72
+ parsed.title = rest[index + 1];
73
+ if (!parsed.title) {
74
+ return { error: 'Missing title after --title.' };
75
+ }
76
+ index += 1;
77
+ continue;
78
+ }
79
+ if (token === '--family-tag') {
80
+ const tag = rest[index + 1];
81
+ if (!tag) {
82
+ return { error: 'Missing tag after --family-tag.' };
83
+ }
84
+ parsed.familyTags.push(tag);
85
+ index += 1;
86
+ continue;
87
+ }
88
+ if (token === '--related') {
89
+ const related = rest[index + 1];
90
+ if (!related) {
91
+ return { error: 'Missing problem id after --related.' };
92
+ }
93
+ parsed.relatedProblems.push(related);
94
+ index += 1;
95
+ continue;
96
+ }
97
+ if (token === '--formalization-status') {
98
+ parsed.formalizationStatus = rest[index + 1];
99
+ if (!parsed.formalizationStatus) {
100
+ return { error: 'Missing value after --formalization-status.' };
101
+ }
102
+ index += 1;
103
+ continue;
104
+ }
105
+ if (token === '--active-route') {
106
+ parsed.activeRoute = rest[index + 1];
107
+ if (!parsed.activeRoute) {
108
+ return { error: 'Missing value after --active-route.' };
109
+ }
110
+ index += 1;
111
+ continue;
112
+ }
113
+ if (token === '--route-breakthrough') {
114
+ parsed.routeBreakthrough = true;
115
+ continue;
116
+ }
117
+ if (token === '--problem-solved') {
118
+ parsed.problemSolved = true;
119
+ continue;
120
+ }
121
+ if (token === '--dest-root') {
122
+ parsed.destRoot = rest[index + 1];
123
+ if (!parsed.destRoot) {
124
+ return { error: 'Missing path after --dest-root.' };
125
+ }
126
+ index += 1;
127
+ continue;
128
+ }
129
+ if (token === '--no-activate') {
130
+ parsed.noActivate = true;
131
+ continue;
132
+ }
133
+ if (token === '--no-loop-sync') {
134
+ parsed.noLoopSync = true;
135
+ continue;
136
+ }
137
+ if (token === '--force') {
138
+ parsed.force = true;
139
+ continue;
140
+ }
141
+ if (token === '--json') {
142
+ parsed.asJson = true;
143
+ continue;
144
+ }
145
+ return { error: `Unknown seed option: ${token}` };
146
+ }
147
+
148
+ return parsed;
149
+ }
150
+
151
+ export async function runSeedCommand(args) {
152
+ if (args.length === 0 || args[0] === 'help' || args[0] === '--help') {
153
+ console.log('Usage:');
154
+ console.log(' erdos seed problem <id> [--include-site] [--refresh-upstream] [--cluster <name>] [--repo-status <status>] [--harness-depth <depth>] [--title <title>] [--family-tag <tag>] [--related <id>] [--formalization-status <status>] [--active-route <route>] [--route-breakthrough] [--problem-solved] [--dest-root <path>] [--no-activate] [--no-loop-sync] [--force] [--json]');
155
+ return 0;
156
+ }
157
+
158
+ const parsed = parseSeedArgs(args);
159
+ if (parsed.error) {
160
+ console.error(parsed.error);
161
+ return 1;
162
+ }
163
+ if (!parsed.problemId) {
164
+ console.error('Missing problem id.');
165
+ return 1;
166
+ }
167
+
168
+ const workspaceRoot = getWorkspaceRoot();
169
+ const pullDir = getWorkspaceProblemPullDir(parsed.problemId, workspaceRoot);
170
+ const defaultSeedRoot = getWorkspaceSeededProblemsDir(workspaceRoot);
171
+ const destinationRoot = parsed.destRoot
172
+ ? path.resolve(parsed.destRoot)
173
+ : defaultSeedRoot;
174
+ const seedsIntoWorkspaceOverlay = destinationRoot === defaultSeedRoot;
175
+
176
+ const pullArgs = ['problem', String(parsed.problemId), '--dest', pullDir];
177
+ if (parsed.includeSite) {
178
+ pullArgs.push('--include-site');
179
+ }
180
+ if (parsed.refreshUpstream) {
181
+ pullArgs.push('--refresh-upstream');
182
+ }
183
+
184
+ const pullExit = await runPullCommand(pullArgs, { silent: parsed.asJson });
185
+ if (pullExit !== 0) {
186
+ return pullExit;
187
+ }
188
+
189
+ const packageProblem = getProblem(parsed.problemId, workspaceRoot);
190
+ const result = seedProblemFromPullBundle(parsed.problemId, {
191
+ fromPullDir: pullDir,
192
+ destRoot: destinationRoot,
193
+ cluster: parsed.cluster ?? packageProblem?.cluster ?? 'uncategorized',
194
+ repoStatus: parsed.repoStatus,
195
+ harnessDepth: parsed.harnessDepth,
196
+ title: parsed.title,
197
+ familyTags: parsed.familyTags,
198
+ relatedProblems: parsed.relatedProblems,
199
+ formalizationStatus: parsed.formalizationStatus,
200
+ activeRoute: parsed.activeRoute ?? (parsed.problemSolved ? null : 'seed_route_pending'),
201
+ routeBreakthrough: parsed.routeBreakthrough,
202
+ problemSolved: parsed.problemSolved,
203
+ force: parsed.force,
204
+ });
205
+
206
+ const activated = !parsed.noActivate && seedsIntoWorkspaceOverlay;
207
+ const loopSynced = !parsed.noLoopSync && activated;
208
+
209
+ let state = null;
210
+ let checkpoints = null;
211
+ if (activated) {
212
+ setCurrentProblem(parsed.problemId, workspaceRoot);
213
+ }
214
+ if (loopSynced) {
215
+ state = syncState(workspaceRoot);
216
+ checkpoints = syncCheckpoints(workspaceRoot);
217
+ }
218
+
219
+ const payload = {
220
+ problemId: String(parsed.problemId),
221
+ pullDir,
222
+ destinationDir: result.destinationDir,
223
+ cluster: result.record.cluster,
224
+ harnessDepth: result.record.harness.depth,
225
+ title: result.record.title,
226
+ activated,
227
+ loopSynced,
228
+ activeProblem: activated ? readCurrentProblem(workspaceRoot) : null,
229
+ activeRoute: state?.activeRoute ?? null,
230
+ nextHonestMove: state?.nextHonestMove ?? null,
231
+ checkpointShelf: checkpoints?.indexPath ?? null,
232
+ usedUpstreamRecord: result.usedUpstreamRecord,
233
+ usedSiteSnapshot: result.usedSiteSnapshot,
234
+ workspaceOverlayVisible: seedsIntoWorkspaceOverlay,
235
+ };
236
+
237
+ if (parsed.asJson) {
238
+ console.log(JSON.stringify(payload, null, 2));
239
+ return 0;
240
+ }
241
+
242
+ console.log(`Seeded local dossier for problem ${parsed.problemId}`);
243
+ console.log(`Pull bundle: ${pullDir}`);
244
+ console.log(`Destination: ${result.destinationDir}`);
245
+ console.log(`Title: ${result.record.title}`);
246
+ console.log(`Cluster: ${result.record.cluster}`);
247
+ console.log(`Harness depth: ${result.record.harness.depth}`);
248
+ console.log(`Upstream record used: ${result.usedUpstreamRecord ? 'yes' : 'no'}`);
249
+ console.log(`Site snapshot used: ${result.usedSiteSnapshot ? 'yes' : 'no'}`);
250
+ console.log(`Workspace overlay visible: ${seedsIntoWorkspaceOverlay ? 'yes' : 'no'}`);
251
+ console.log(`Activated: ${activated ? 'yes' : 'no'}`);
252
+ console.log(`Loop synced: ${loopSynced ? 'yes' : 'no'}`);
253
+ if (!seedsIntoWorkspaceOverlay && (!parsed.noActivate || !parsed.noLoopSync)) {
254
+ console.log('Note: activation and loop sync were skipped because --dest-root points outside .erdos/seeded-problems.');
255
+ }
256
+ if (state) {
257
+ console.log(`Active route: ${state.activeRoute ?? '(none)'}`);
258
+ console.log(`Next honest move: ${state.nextHonestMove}`);
259
+ }
260
+ if (checkpoints) {
261
+ console.log(`Checkpoint shelf: ${checkpoints.indexPath}`);
262
+ }
263
+ return 0;
264
+ }
@@ -44,6 +44,16 @@ function printSunflowerStatus(snapshot, registryPaths) {
44
44
  console.log(`Literature focus: ${snapshot.literatureFocus.join(', ') || '(none)'}`);
45
45
  console.log(`Artifact focus: ${snapshot.artifactFocus.join(', ') || '(none)'}`);
46
46
  console.log(`Context file: ${snapshot.contextPath ?? '(none)'}`);
47
+ console.log(`Route packet present: ${snapshot.routePacketPresent ? 'yes' : 'no'}`);
48
+ if (snapshot.routePacket) {
49
+ console.log(`Route packet id: ${snapshot.routePacket.routePacketId ?? '(none)'}`);
50
+ console.log(`Route packet route: ${snapshot.routePacket.routeId ?? '(none)'}`);
51
+ console.log(`Route frontier claim: ${snapshot.routePacket.frontierClaim ?? '(none)'}`);
52
+ console.log(`Theorem module: ${snapshot.routePacket.theoremModule ?? '(none)'}`);
53
+ }
54
+ console.log(`Agent start packet: ${snapshot.agentStartPresent ? snapshot.agentStartPath : '(missing)'}`);
55
+ console.log(`Checkpoint packet: ${snapshot.checkpointPacketPresent ? snapshot.checkpointPacketPath : '(missing)'}`);
56
+ console.log(`Report packet: ${snapshot.reportPacketPresent ? snapshot.reportPacketPath : '(missing)'}`);
47
57
  console.log(`Compute lane present: ${snapshot.computeLanePresent ? 'yes' : 'no'}`);
48
58
  console.log(`Compute lane count: ${snapshot.computeLaneCount}`);
49
59
  console.log(`Compute summary: ${snapshot.computeSummary}`);
@@ -29,10 +29,12 @@ export function runWorkspaceCommand(args) {
29
29
  console.log(`Question ledger: ${summary.questionLedgerPath}`);
30
30
  console.log(`Checkpoint shelf: ${summary.checkpointIndexPath}`);
31
31
  console.log(`Workspace upstream dir: ${summary.upstreamDir}`);
32
+ console.log(`Workspace seeded-problems dir: ${summary.seededProblemsDir}`);
32
33
  console.log(`Workspace scaffold dir: ${summary.scaffoldDir}`);
33
34
  console.log(`Workspace pull dir: ${summary.pullDir}`);
34
35
  console.log(`Workspace artifact dir: ${summary.artifactDir}`);
35
36
  console.log(`Workspace literature dir: ${summary.literatureDir}`);
37
+ console.log(`Active seeded dossier dir: ${summary.seededProblemDir}`);
36
38
  console.log(`Preferred agent: ${config.preferredAgent}`);
37
39
  console.log(`Continuation mode: ${summary.continuationMode ?? config.continuation}`);
38
40
  console.log(`Active route: ${summary.activeRoute ?? '(none)'}`);
@@ -4,6 +4,39 @@ import { stringify } from 'yaml';
4
4
  import { ensureDir, fileExists, readJson, readText, writeText } from './files.js';
5
5
  import { getProblemDir, getWorkspaceProblemPullDir, repoRoot } from './paths.js';
6
6
 
7
+ const STATEMENT_SKIP_PATTERNS = [
8
+ /^open$/i,
9
+ /^proved(?:\s*\(.*\))?$/i,
10
+ /^disproved(?:\s*\(.*\))?$/i,
11
+ /^decidable$/i,
12
+ /^verifiable$/i,
13
+ /^erd[őo]s problem #\d+/i,
14
+ /^this has been solved/i,
15
+ /^-\s*\$\d+/i,
16
+ /^-$/i,
17
+ /^#\d+\s*:/i,
18
+ /^forum$/i,
19
+ /^inbox$/i,
20
+ /^favourites$/i,
21
+ /^tags$/i,
22
+ /^more$/i,
23
+ /^faq$/i,
24
+ /^prizes$/i,
25
+ /^view the latex source$/i,
26
+ /^view history$/i,
27
+ /^external data from the database/i,
28
+ /^formalised statement\?$/i,
29
+ /\bdisclaimer\b/i,
30
+ /^this is (open|proved|disproved|verifiable|decidable)\b/i,
31
+ /^\s*[a-z][a-z ]+\|\s*$/i,
32
+ ];
33
+
34
+ const STARTER_LOOP_ARTIFACTS = [
35
+ 'AGENT_START.md',
36
+ 'ROUTES.md',
37
+ 'CHECKPOINT_NOTES.md',
38
+ ];
39
+
7
40
  function normalizeTitle(rawTitle, problemId) {
8
41
  const fallback = `Erdos Problem #${problemId}`;
9
42
  if (!rawTitle) {
@@ -29,6 +62,34 @@ function uppercaseBadge(status) {
29
62
  return String(status ?? 'unknown').trim().toUpperCase() || 'UNKNOWN';
30
63
  }
31
64
 
65
+ function normalizeClusterLabel(rawTag) {
66
+ return String(rawTag ?? '')
67
+ .trim()
68
+ .toLowerCase()
69
+ .replace(/[^a-z0-9]+/g, '-')
70
+ .replace(/^-+|-+$/g, '');
71
+ }
72
+
73
+ function inferClusterFromTags(tags) {
74
+ const normalized = Array.isArray(tags) ? tags.map(normalizeClusterLabel).filter(Boolean) : [];
75
+ if (normalized.includes('number-theory')) {
76
+ return 'number-theory';
77
+ }
78
+ if (normalized.includes('graph-theory') || normalized.includes('chromatic-number')) {
79
+ return 'graph-theory';
80
+ }
81
+ if (normalized.includes('geometry')) {
82
+ return 'geometry';
83
+ }
84
+ if (normalized.includes('analysis')) {
85
+ return 'analysis';
86
+ }
87
+ if (normalized.includes('combinatorics') || normalized.includes('intersecting-family')) {
88
+ return 'combinatorics';
89
+ }
90
+ return 'uncategorized';
91
+ }
92
+
32
93
  function getDefaultPullDir(problemId) {
33
94
  return getWorkspaceProblemPullDir(problemId);
34
95
  }
@@ -84,12 +145,22 @@ function deriveTitle(problemId, bundle, titleOverride) {
84
145
  return `Erdos Problem #${problemId}`;
85
146
  }
86
147
 
148
+ function extractStatementCandidates(bundle) {
149
+ const previewLines = Array.isArray(bundle.siteExtract?.previewLines)
150
+ ? bundle.siteExtract.previewLines
151
+ : [];
152
+
153
+ return previewLines
154
+ .map((line) => String(line ?? '').replace(/\s+/g, ' ').trim())
155
+ .filter(Boolean)
156
+ .filter((line) => !STATEMENT_SKIP_PATTERNS.some((pattern) => pattern.test(line)))
157
+ .filter((line) => !/^\w[\w -]+$/.test(line) || line.length > 40);
158
+ }
159
+
87
160
  function deriveShortStatement(problemId, bundle, title) {
88
- const preview = Array.isArray(bundle.siteExtract?.previewLines)
89
- ? bundle.siteExtract.previewLines.find((line) => String(line ?? '').trim())
90
- : null;
91
- if (preview) {
92
- return String(preview).replace(/\s+/g, ' ').trim();
161
+ const statementCandidate = extractStatementCandidates(bundle)[0];
162
+ if (statementCandidate) {
163
+ return statementCandidate;
93
164
  }
94
165
  if (bundle.problemRecord?.title && bundle.problemRecord.title !== title) {
95
166
  return String(bundle.problemRecord.title).trim();
@@ -157,7 +228,7 @@ function buildProblemRecord(problemId, bundle, options) {
157
228
  upstream_status: upstreamRecord.status?.state ?? null,
158
229
  upstream_last_update: upstreamRecord.status?.last_update ?? null,
159
230
  },
160
- cluster: options.cluster,
231
+ cluster: options.cluster ?? inferClusterFromTags(upstreamRecord.tags),
161
232
  prize: {
162
233
  display: upstreamRecord.prize ?? 'unknown',
163
234
  },
@@ -191,6 +262,7 @@ function renderStatementMarkdown(problemId, record, bundle) {
191
262
  const previewLines = Array.isArray(bundle.siteExtract?.previewLines)
192
263
  ? bundle.siteExtract.previewLines.filter((line) => String(line ?? '').trim())
193
264
  : [];
265
+ const statementCandidates = extractStatementCandidates(bundle);
194
266
 
195
267
  return [
196
268
  `# Problem ${problemId} Statement`,
@@ -199,8 +271,19 @@ function renderStatementMarkdown(problemId, record, bundle) {
199
271
  '',
200
272
  'Normalized focus:',
201
273
  `- ${record.statement.short}`,
202
- previewLines.length > 0 ? '- Seeded with preview lines from the public site snapshot' : '- Seeded from upstream public metadata',
274
+ statementCandidates.length > 0
275
+ ? '- Seeded with filtered statement candidates from the public site snapshot'
276
+ : previewLines.length > 0
277
+ ? '- Seeded with preview lines from the public site snapshot'
278
+ : '- Seeded from upstream public metadata',
203
279
  '',
280
+ ...(statementCandidates.length > 0
281
+ ? [
282
+ 'Statement candidates:',
283
+ ...statementCandidates.slice(0, 4).map((line) => `- ${line}`),
284
+ '',
285
+ ]
286
+ : []),
204
287
  ...(previewLines.length > 0
205
288
  ? [
206
289
  'Public-site preview:',
@@ -256,6 +339,69 @@ function renderFormalizationMarkdown(record) {
256
339
  ].join('\n');
257
340
  }
258
341
 
342
+ function renderAgentStartMarkdown(problemId, record) {
343
+ const activeRoute = record.research_state?.active_route ?? 'seed_route_pending';
344
+ const routeMode = activeRoute ? 'route' : 'milestone';
345
+ return [
346
+ '# Agent Start',
347
+ '',
348
+ 'Fast start:',
349
+ `- \`erdos problem show ${problemId}\``,
350
+ '- `erdos workspace show`',
351
+ '- `erdos preflight`',
352
+ `- \`erdos continuation use ${routeMode}\``,
353
+ '- `erdos checkpoints sync`',
354
+ '',
355
+ 'Working assumptions:',
356
+ `- Open problem: ${record.research_state?.open_problem === false ? 'no' : 'yes'}`,
357
+ `- Active route: ${activeRoute}`,
358
+ `- Repo status: ${record.status.repo_status}`,
359
+ `- Harness depth: ${record.harness.depth}`,
360
+ '',
361
+ 'First honest move:',
362
+ `- tighten the local dossier for problem ${problemId} against its pull bundle, references, and upstream provenance before widening claims.`,
363
+ '',
364
+ ].join('\n');
365
+ }
366
+
367
+ function renderRoutesMarkdown(problemId, record) {
368
+ const activeRoute = record.research_state?.active_route ?? 'seed_route_pending';
369
+ return [
370
+ '# Routes',
371
+ '',
372
+ '## Status Ladder',
373
+ '',
374
+ `- Open problem: ${record.research_state?.open_problem === false ? 'no' : 'yes'}`,
375
+ `- Active route: ${activeRoute}`,
376
+ `- Route breakthrough: ${record.research_state?.route_breakthrough ? 'yes' : 'no'}`,
377
+ `- Problem solved: ${record.research_state?.problem_solved ? 'yes' : 'no'}`,
378
+ '',
379
+ '## Starter route notes',
380
+ '',
381
+ `- Current seeded route placeholder for problem ${problemId}: \`${activeRoute}\``,
382
+ '- Treat this as a workspace-level route marker until a curated route tree is written.',
383
+ '- Keep route progress separate from global problem status.',
384
+ '',
385
+ ].join('\n');
386
+ }
387
+
388
+ function renderCheckpointNotesMarkdown(problemId, record) {
389
+ return [
390
+ '# Checkpoint Notes',
391
+ '',
392
+ `- Problem: ${problemId}`,
393
+ `- Repo status: ${record.status.repo_status}`,
394
+ `- Harness depth: ${record.harness.depth}`,
395
+ '',
396
+ 'Checkpoint prompts:',
397
+ '- What changed in the active route since the last honest checkpoint?',
398
+ '- Which claim level is justified right now: Exact, Verified, Heuristic, or Conjecture?',
399
+ '- Which upstream/public truth changed, if any?',
400
+ '- Which artifact or literature bundle should the next agent read first?',
401
+ '',
402
+ ].join('\n');
403
+ }
404
+
259
405
  export function seedProblemFromPullBundle(problemId, options = {}) {
260
406
  const bundle = loadPullBundle(problemId, options.fromPullDir);
261
407
  const destinationRoot = path.resolve(options.destRoot ?? path.join(repoRoot, 'problems'));
@@ -267,7 +413,7 @@ export function seedProblemFromPullBundle(problemId, options = {}) {
267
413
 
268
414
  ensureDir(destinationDir);
269
415
  const record = buildProblemRecord(problemId, bundle, {
270
- cluster: options.cluster ?? 'uncategorized',
416
+ cluster: options.cluster ?? null,
271
417
  repoStatus: options.repoStatus ?? 'cataloged',
272
418
  harnessDepth: options.harnessDepth ?? 'dossier',
273
419
  title: options.title ?? null,
@@ -284,11 +430,15 @@ export function seedProblemFromPullBundle(problemId, options = {}) {
284
430
  writeText(path.join(destinationDir, 'REFERENCES.md'), renderReferencesMarkdown(record, bundle));
285
431
  writeText(path.join(destinationDir, 'EVIDENCE.md'), renderEvidenceMarkdown(problemId, record, bundle));
286
432
  writeText(path.join(destinationDir, 'FORMALIZATION.md'), renderFormalizationMarkdown(record));
433
+ writeText(path.join(destinationDir, 'AGENT_START.md'), renderAgentStartMarkdown(problemId, record));
434
+ writeText(path.join(destinationDir, 'ROUTES.md'), renderRoutesMarkdown(problemId, record));
435
+ writeText(path.join(destinationDir, 'CHECKPOINT_NOTES.md'), renderCheckpointNotesMarkdown(problemId, record));
287
436
 
288
437
  return {
289
438
  destinationDir,
290
439
  record,
291
440
  usedSiteSnapshot: Boolean(bundle.siteExtract || bundle.siteSummary),
292
441
  usedUpstreamRecord: Boolean(bundle.upstreamRecord),
442
+ starterLoopArtifacts: STARTER_LOOP_ARTIFACTS,
293
443
  };
294
444
  }