erdos-problems 0.1.13 → 0.2.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.
Files changed (60) hide show
  1. package/README.md +117 -4
  2. package/docs/RESEARCH_LOOP.md +21 -2
  3. package/package.json +1 -1
  4. package/packs/number-theory/README.md +17 -0
  5. package/packs/number-theory/problems/1/CHECKPOINT_TEMPLATE.md +7 -0
  6. package/packs/number-theory/problems/1/CONTEXT.md +8 -0
  7. package/packs/number-theory/problems/1/FRONTIER_NOTE.md +8 -0
  8. package/packs/number-theory/problems/1/OPS_DETAILS.yaml +25 -0
  9. package/packs/number-theory/problems/1/REPORT_TEMPLATE.md +7 -0
  10. package/packs/number-theory/problems/1/ROUTE_HISTORY.md +5 -0
  11. package/packs/number-theory/problems/1/ROUTE_PACKET.yaml +13 -0
  12. package/packs/number-theory/problems/1/context.yaml +25 -0
  13. package/packs/number-theory/problems/2/CHECKPOINT_TEMPLATE.md +7 -0
  14. package/packs/number-theory/problems/2/CONTEXT.md +8 -0
  15. package/packs/number-theory/problems/2/FRONTIER_NOTE.md +8 -0
  16. package/packs/number-theory/problems/2/OPS_DETAILS.yaml +25 -0
  17. package/packs/number-theory/problems/2/REPORT_TEMPLATE.md +7 -0
  18. package/packs/number-theory/problems/2/ROUTE_HISTORY.md +5 -0
  19. package/packs/number-theory/problems/2/ROUTE_PACKET.yaml +13 -0
  20. package/packs/number-theory/problems/2/context.yaml +25 -0
  21. package/packs/sunflower/README.md +17 -4
  22. package/packs/sunflower/problems/20/CHECKPOINT_TEMPLATE.md +29 -0
  23. package/packs/sunflower/problems/20/FRONTIER_NOTE.md +13 -0
  24. package/packs/sunflower/problems/20/OPS_DETAILS.yaml +44 -0
  25. package/packs/sunflower/problems/20/REPORT_TEMPLATE.md +23 -0
  26. package/packs/sunflower/problems/20/ROUTE_HISTORY.md +18 -0
  27. package/packs/sunflower/problems/536/CHECKPOINT_TEMPLATE.md +7 -0
  28. package/packs/sunflower/problems/536/FRONTIER_NOTE.md +8 -0
  29. package/packs/sunflower/problems/536/OPS_DETAILS.yaml +39 -0
  30. package/packs/sunflower/problems/536/REPORT_TEMPLATE.md +7 -0
  31. package/packs/sunflower/problems/536/ROUTE_HISTORY.md +5 -0
  32. package/packs/sunflower/problems/856/CHECKPOINT_TEMPLATE.md +7 -0
  33. package/packs/sunflower/problems/856/FRONTIER_NOTE.md +8 -0
  34. package/packs/sunflower/problems/856/OPS_DETAILS.yaml +39 -0
  35. package/packs/sunflower/problems/856/REPORT_TEMPLATE.md +7 -0
  36. package/packs/sunflower/problems/856/ROUTE_HISTORY.md +5 -0
  37. package/packs/sunflower/problems/857/CHECKPOINT_TEMPLATE.md +32 -0
  38. package/packs/sunflower/problems/857/FRONTIER_NOTE.md +18 -0
  39. package/packs/sunflower/problems/857/OPS_DETAILS.yaml +65 -0
  40. package/packs/sunflower/problems/857/REPORT_TEMPLATE.md +26 -0
  41. package/packs/sunflower/problems/857/ROUTE_HISTORY.md +25 -0
  42. package/src/cli/index.js +22 -3
  43. package/src/commands/archive.js +46 -0
  44. package/src/commands/cluster.js +4 -0
  45. package/src/commands/maintainer.js +20 -2
  46. package/src/commands/number-theory.js +199 -0
  47. package/src/commands/problem.js +3 -0
  48. package/src/commands/pull.js +180 -5
  49. package/src/commands/sunflower.js +290 -12
  50. package/src/commands/upstream.js +129 -0
  51. package/src/commands/workspace.js +20 -0
  52. package/src/runtime/archive.js +87 -0
  53. package/src/runtime/checkpoints.js +27 -0
  54. package/src/runtime/maintainer-seed.js +70 -0
  55. package/src/runtime/number-theory.js +169 -0
  56. package/src/runtime/paths.js +16 -0
  57. package/src/runtime/state.js +63 -3
  58. package/src/runtime/sunflower.js +329 -2
  59. package/src/runtime/workspace.js +4 -0
  60. package/src/upstream/literature.js +83 -0
@@ -62,6 +62,13 @@ function renderProblemCheckpoint(problem, state) {
62
62
 
63
63
  - ${checkpointFocus}
64
64
 
65
+ ## Pack Context
66
+
67
+ - Frontier Note: ${sunflower?.frontierNotePath ?? '(none)'}
68
+ - Route History: ${sunflower?.routeHistoryPath ?? '(none)'}
69
+ - Checkpoint Template: ${sunflower?.checkpointTemplatePath ?? '(none)'}
70
+ - Report Template: ${sunflower?.reportTemplatePath ?? '(none)'}
71
+
65
72
  ## Next Honest Move
66
73
 
67
74
  - ${nextHonestMove}
@@ -92,6 +99,20 @@ function renderRouteCheckpoint(problem, state) {
92
99
  const mirageLine = sunflower
93
100
  ? `- Mirage Frontiers: ${sunflower.mirageFrontierCount}`
94
101
  : null;
102
+ const routeDetailLine = sunflower?.activeRouteDetail?.summary
103
+ ? `- Route Detail: ${sunflower.activeRouteDetail.summary}`
104
+ : null;
105
+ const ticketDetailLine = sunflower?.activeTicketDetail?.currentBlocker
106
+ ? `- Ticket Blocker: ${sunflower.activeTicketDetail.currentBlocker}`
107
+ : null;
108
+ const packArtifactLines = sunflower
109
+ ? [
110
+ `- Frontier Note: ${sunflower.frontierNotePath ?? '(none)'}`,
111
+ `- Route History: ${sunflower.routeHistoryPath ?? '(none)'}`,
112
+ `- Checkpoint Template: ${sunflower.checkpointTemplatePath ?? '(none)'}`,
113
+ `- Report Template: ${sunflower.reportTemplatePath ?? '(none)'}`,
114
+ ].join('\n')
115
+ : null;
95
116
 
96
117
  return `# Problem ${problem.problemId} Active Route Checkpoint
97
118
 
@@ -107,6 +128,8 @@ function renderRouteCheckpoint(problem, state) {
107
128
  - ${frontier}
108
129
  ${activeTicketLine}
109
130
  ${readyAtomLine}
131
+ ${routeDetailLine ? `\n${routeDetailLine}` : ''}
132
+ ${ticketDetailLine ? `\n${ticketDetailLine}` : ''}
110
133
  ${mirageLine ? `\n${mirageLine}` : ''}
111
134
 
112
135
  ## Route Story
@@ -117,6 +140,10 @@ ${mirageLine ? `\n${mirageLine}` : ''}
117
140
 
118
141
  - ${checkpointFocus}
119
142
 
143
+ ## Pack Artifacts
144
+
145
+ ${packArtifactLines ?? '- Frontier Note: *(none)*'}
146
+
120
147
  ## Continuation Frame
121
148
 
122
149
  - Continuation mode: ${state.continuation.mode}
@@ -397,9 +397,18 @@ function renderAgentStartMarkdown(problemId, record) {
397
397
  `- Harness depth: ${record.harness.depth}`,
398
398
  `- Site status: ${record.status.site_status}`,
399
399
  '',
400
+ 'Read in this order:',
401
+ '- `STATEMENT.md`',
402
+ '- `REFERENCES.md`',
403
+ '- `EVIDENCE.md`',
404
+ '- `FORMALIZATION.md`',
405
+ '- `PUBLIC_STATUS_REVIEW.md`',
406
+ '- `AGENT_WEBSEARCH_BRIEF.md`',
407
+ '',
400
408
  'First honest move:',
401
409
  `- tighten the local dossier for problem ${problemId} against its pull bundle, references, and upstream provenance before widening claims.`,
402
410
  '- read `PUBLIC_STATUS_REVIEW.md` and run the suggested queries in `AGENT_WEBSEARCH_BRIEF.md` before trusting a single public status surface.',
411
+ '- write down the smallest route hypothesis that would make the next session cleaner, even if it remains provisional.',
403
412
  '',
404
413
  ].join('\n');
405
414
  }
@@ -421,6 +430,10 @@ function renderRoutesMarkdown(problemId, record) {
421
430
  `- Current seeded route placeholder for problem ${problemId}: \`${activeRoute}\``,
422
431
  '- Treat this as a workspace-level route marker until a curated route tree is written.',
423
432
  '- Keep route progress separate from global problem status.',
433
+ '- Suggested route-writing prompts:',
434
+ ' - What is the smallest honest route name?',
435
+ ' - What theorem, evidence bundle, or survey note does it point at?',
436
+ ' - What would count as a route breakthrough versus only route clarification?',
424
437
  '',
425
438
  ].join('\n');
426
439
  }
@@ -439,6 +452,7 @@ function renderCheckpointNotesMarkdown(problemId, record) {
439
452
  '- Which upstream/public truth changed, if any?',
440
453
  '- What did the public-status review and agent websearch brief surface beyond erdosproblems.com?',
441
454
  '- Which artifact or literature bundle should the next agent read first?',
455
+ '- What route, evidence, and formalization notes should be promoted out of scratch space into canonical dossier files?',
442
456
  '',
443
457
  ].join('\n');
444
458
  }
@@ -508,3 +522,59 @@ export function seedProblemFromPullBundle(problemId, options = {}) {
508
522
  starterLoopArtifacts: STARTER_LOOP_ARTIFACTS,
509
523
  };
510
524
  }
525
+
526
+ function renderReviewChecklist(problemId, bundle, destinationDir) {
527
+ return [
528
+ `# Problem ${problemId} Maintainer Review Checklist`,
529
+ '',
530
+ `- Pull bundle: ${bundle.pullDir}`,
531
+ `- Proposed destination: ${destinationDir}`,
532
+ '',
533
+ '## Provenance',
534
+ '',
535
+ `- Upstream record included: ${bundle.upstreamRecord ? 'yes' : 'no'}`,
536
+ `- Site snapshot included: ${bundle.siteExtract || bundle.siteSummary ? 'yes' : 'no'}`,
537
+ `- Public search review included: ${bundle.publicStatusReview || bundle.publicStatusReviewMarkdown ? 'yes' : 'no'}`,
538
+ '',
539
+ '## Review questions',
540
+ '',
541
+ '- Is the public site status clearly open right now?',
542
+ '- Does the seeded short statement capture the actual mathematical focus cleanly?',
543
+ '- Are the cluster and family tags honest?',
544
+ '- Does the dossier need a deeper route starter before publication?',
545
+ '- Should this problem remain dossier-depth or enter a family pack later?',
546
+ '',
547
+ '## Ready-to-promote checks',
548
+ '',
549
+ '- Statement reviewed',
550
+ '- References reviewed',
551
+ '- Evidence starter reviewed',
552
+ '- Formalization starter reviewed',
553
+ '- Public-status review read',
554
+ '- Agent websearch brief read',
555
+ '',
556
+ ].join('\n');
557
+ }
558
+
559
+ export function reviewPullBundleForSeeding(problemId, options = {}) {
560
+ const bundle = loadPullBundle(problemId, options.fromPullDir);
561
+ const destinationRoot = path.resolve(options.destRoot ?? path.join(repoRoot, 'problems'));
562
+ const destinationDir = path.join(destinationRoot, String(problemId));
563
+ const reviewPath = path.resolve(options.dest ?? path.join(bundle.pullDir, 'REVIEW_CHECKLIST.md'));
564
+ const title = deriveTitle(problemId, bundle, options.title);
565
+ const shortStatement = deriveShortStatement(problemId, bundle, title);
566
+
567
+ writeText(reviewPath, renderReviewChecklist(problemId, bundle, destinationDir));
568
+
569
+ return {
570
+ problemId: String(problemId),
571
+ reviewPath,
572
+ pullDir: bundle.pullDir,
573
+ destinationDir,
574
+ usedUpstreamRecord: Boolean(bundle.upstreamRecord),
575
+ usedSiteSnapshot: Boolean(bundle.siteExtract || bundle.siteSummary),
576
+ usedPublicStatusReview: Boolean(bundle.publicStatusReview || bundle.publicStatusReviewMarkdown),
577
+ title,
578
+ shortStatement,
579
+ };
580
+ }
@@ -0,0 +1,169 @@
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 findActiveRouteDetail(opsDetails, activeRoute) {
43
+ if (!opsDetails || !Array.isArray(opsDetails.routes)) {
44
+ return null;
45
+ }
46
+ return opsDetails.routes.find((route) => route.route_id === activeRoute) ?? opsDetails.routes[0] ?? null;
47
+ }
48
+
49
+ function findActiveTicketDetail(opsDetails, activeRoute) {
50
+ if (!opsDetails || !Array.isArray(opsDetails.tickets)) {
51
+ return null;
52
+ }
53
+ return (
54
+ opsDetails.tickets.find((ticket) => ticket.status === 'active' && (!activeRoute || ticket.route_id === activeRoute))
55
+ ?? opsDetails.tickets.find((ticket) => !activeRoute || ticket.route_id === activeRoute)
56
+ ?? opsDetails.tickets[0]
57
+ ?? null
58
+ );
59
+ }
60
+
61
+ function findFirstReadyAtom(opsDetails, activeRoute) {
62
+ if (!opsDetails || !Array.isArray(opsDetails.atoms)) {
63
+ return null;
64
+ }
65
+ return (
66
+ opsDetails.atoms.find((atom) => atom.status === 'ready' && (!activeRoute || atom.route_id === activeRoute))
67
+ ?? opsDetails.atoms.find((atom) => atom.status === 'ready')
68
+ ?? null
69
+ );
70
+ }
71
+
72
+ function resolveArchiveMode(problem) {
73
+ const siteStatus = String(problem.siteStatus ?? '').toLowerCase();
74
+ if (siteStatus === 'solved') {
75
+ return 'method_exemplar';
76
+ }
77
+ if (siteStatus === 'disproved') {
78
+ return 'counterexample_archive';
79
+ }
80
+ return null;
81
+ }
82
+
83
+ export function buildNumberTheoryStatusSnapshot(problem) {
84
+ const contextPath = getPackFile(problem.problemId, 'context.yaml');
85
+ const contextMarkdownPath = getPackFile(problem.problemId, 'CONTEXT.md');
86
+ const routePacketPath = getPackFile(problem.problemId, 'ROUTE_PACKET.yaml');
87
+ const frontierNotePath = getPackFile(problem.problemId, 'FRONTIER_NOTE.md');
88
+ const routeHistoryPath = getPackFile(problem.problemId, 'ROUTE_HISTORY.md');
89
+ const checkpointTemplatePath = getPackFile(problem.problemId, 'CHECKPOINT_TEMPLATE.md');
90
+ const reportTemplatePath = getPackFile(problem.problemId, 'REPORT_TEMPLATE.md');
91
+
92
+ const context = readYamlIfPresent(contextPath) ?? {};
93
+ const routePacket = readYamlIfPresent(routePacketPath);
94
+ const opsDetails = parseOpsDetails(problem.problemId);
95
+
96
+ const activeRoute =
97
+ problem.researchState?.active_route
98
+ ?? context.default_active_route
99
+ ?? routePacket?.route_id
100
+ ?? null;
101
+ const routeBreakthrough = typeof problem.researchState?.route_breakthrough === 'boolean'
102
+ ? problem.researchState.route_breakthrough
103
+ : false;
104
+ const archiveMode = resolveArchiveMode(problem);
105
+ const problemSolved = typeof problem.researchState?.problem_solved === 'boolean'
106
+ ? problem.researchState.problem_solved
107
+ : String(problem.siteStatus ?? '').toLowerCase() === 'solved';
108
+ const openProblem = typeof problem.researchState?.open_problem === 'boolean'
109
+ ? problem.researchState.open_problem
110
+ : String(problem.siteStatus ?? '').toLowerCase() === 'open';
111
+
112
+ const activeRouteDetail = findActiveRouteDetail(opsDetails, activeRoute);
113
+ const activeTicketDetail = findActiveTicketDetail(opsDetails, activeRoute);
114
+ const firstReadyAtom = findFirstReadyAtom(opsDetails, activeRoute);
115
+ const readyAtoms = Array.isArray(opsDetails?.atoms)
116
+ ? opsDetails.atoms.filter((atom) => atom.status === 'ready')
117
+ : [];
118
+
119
+ return {
120
+ generatedAt: new Date().toISOString(),
121
+ problemId: problem.problemId,
122
+ displayName: problem.displayName,
123
+ title: problem.title,
124
+ cluster: problem.cluster,
125
+ familyRole: context.family_role ?? 'number_theory_pack',
126
+ harnessProfile: context.harness_profile ?? 'starter_cockpit',
127
+ activeRoute,
128
+ routeBreakthrough,
129
+ problemSolved,
130
+ openProblem,
131
+ siteStatus: problem.siteStatus,
132
+ archiveMode,
133
+ bootstrapFocus: context.bootstrap_focus ?? null,
134
+ routeStory: context.route_story ?? routePacket?.frontier_claim ?? problem.shortStatement,
135
+ frontierLabel: context.frontier_label ?? activeRoute ?? 'number_theory_frontier',
136
+ frontierDetail: firstReadyAtom?.summary ?? context.frontier_detail ?? activeRouteDetail?.summary ?? problem.shortStatement,
137
+ checkpointFocus: context.checkpoint_focus ?? activeRouteDetail?.why_now ?? null,
138
+ nextHonestMove:
139
+ firstReadyAtom?.next_move
140
+ ?? activeTicketDetail?.next_move
141
+ ?? context.next_honest_move
142
+ ?? 'Pull the dossier, freeze the route note, and preserve public-status honesty.',
143
+ relatedCoreProblems: context.related_core_problems ?? [],
144
+ literatureFocus: context.literature_focus ?? [],
145
+ artifactFocus: context.artifact_focus ?? [],
146
+ questionLedger: normalizeQuestionLedger(context.question_ledger),
147
+ contextPresent: fs.existsSync(contextPath),
148
+ contextPath,
149
+ contextMarkdownPath,
150
+ routePacketPresent: Boolean(routePacket),
151
+ routePacket,
152
+ routePacketPath,
153
+ frontierNotePresent: fs.existsSync(frontierNotePath),
154
+ frontierNotePath,
155
+ routeHistoryPresent: fs.existsSync(routeHistoryPath),
156
+ routeHistoryPath,
157
+ checkpointTemplatePresent: fs.existsSync(checkpointTemplatePath),
158
+ checkpointTemplatePath,
159
+ reportTemplatePresent: fs.existsSync(reportTemplatePath),
160
+ reportTemplatePath,
161
+ opsDetailsPresent: Boolean(opsDetails),
162
+ opsDetailsPath: opsDetails?.path ?? getPackFile(problem.problemId, 'OPS_DETAILS.yaml'),
163
+ opsDetails,
164
+ activeRouteDetail,
165
+ activeTicketDetail,
166
+ firstReadyAtom,
167
+ readyAtomCount: readyAtoms.length,
168
+ };
169
+ }
@@ -120,6 +120,22 @@ export function getWorkspaceCheckpointsDir(workspaceRoot = getWorkspaceRoot()) {
120
120
  return path.join(getWorkspaceDir(workspaceRoot), 'checkpoints');
121
121
  }
122
122
 
123
+ export function getWorkspaceRunsDir(workspaceRoot = getWorkspaceRoot()) {
124
+ return path.join(getWorkspaceDir(workspaceRoot), 'runs');
125
+ }
126
+
127
+ export function getWorkspaceRunDir(runId, workspaceRoot = getWorkspaceRoot()) {
128
+ return path.join(getWorkspaceRunsDir(workspaceRoot), String(runId));
129
+ }
130
+
131
+ export function getWorkspaceArchivesDir(workspaceRoot = getWorkspaceRoot()) {
132
+ return path.join(getWorkspaceDir(workspaceRoot), 'archives');
133
+ }
134
+
135
+ export function getWorkspaceArchiveDir(problemId, workspaceRoot = getWorkspaceRoot()) {
136
+ return path.join(getWorkspaceArchivesDir(workspaceRoot), String(problemId));
137
+ }
138
+
123
139
  export function getWorkspaceProblemCheckpointsDir(workspaceRoot = getWorkspaceRoot()) {
124
140
  return path.join(getWorkspaceCheckpointsDir(workspaceRoot), 'problem-checkpoints');
125
141
  }
@@ -7,6 +7,7 @@ import {
7
7
  getWorkspaceStateMarkdownPath,
8
8
  getWorkspaceStatePath,
9
9
  } from './paths.js';
10
+ import { buildNumberTheoryStatusSnapshot } from './number-theory.js';
10
11
  import { buildSunflowerStatusSnapshot } from './sunflower.js';
11
12
  import { readCurrentProblem } from './workspace.js';
12
13
  import { continuationDisplay, resolveContinuation } from './continuation.js';
@@ -35,6 +36,9 @@ function defaultState(config, workspaceRoot) {
35
36
  routeStory: null,
36
37
  checkpointFocus: null,
37
38
  nextHonestMove: 'Select or bootstrap an Erdős problem to begin.',
39
+ packArtifacts: null,
40
+ activeTicketId: null,
41
+ activeAtomId: null,
38
42
  lastCheckpointSyncAt: null,
39
43
  };
40
44
  }
@@ -101,6 +105,13 @@ function renderStateMarkdown(state) {
101
105
 
102
106
  - ${state.checkpointFocus || '(none yet)'}
103
107
 
108
+ ## Pack Artifacts
109
+
110
+ - Frontier Note: ${state.packArtifacts?.frontierNotePath || '(none)'}
111
+ - Route History: ${state.packArtifacts?.routeHistoryPath || '(none)'}
112
+ - Checkpoint Template: ${state.packArtifacts?.checkpointTemplatePath || '(none)'}
113
+ - Report Template: ${state.packArtifacts?.reportTemplatePath || '(none)'}
114
+
104
115
  ## Next Honest Move
105
116
 
106
117
  - ${state.nextHonestMove}
@@ -146,6 +157,9 @@ function deriveGenericProblemSummary(problem) {
146
157
  : 'No active route is recorded for this dossier yet.',
147
158
  checkpointFocus: 'Keep dossier truth, upstream provenance, and local route state sharply separated.',
148
159
  nextHonestMove,
160
+ packArtifacts: null,
161
+ activeTicketId: null,
162
+ activeAtomId: null,
149
163
  questionLedger: {
150
164
  openQuestions: ['What is the next smallest honest route or evidence obligation for this problem?'],
151
165
  activeRouteNotes: activeRoute ? [`Current active route: ${activeRoute}`] : [],
@@ -170,10 +184,10 @@ function deriveProblemSummary(problem) {
170
184
  : sunflower.frontierDetail || sunflower.computeSummary || sunflower.bootstrapFocus || problem.shortStatement;
171
185
  const routeStory = sunflower.activeTicket
172
186
  ? `Work ${sunflower.activeTicket.ticketId} (${sunflower.activeTicket.ticketName}) without blurring ticket-local pressure into solved-problem claims.`
173
- : (sunflower.routeStory || sunflower.bootstrapFocus || null);
187
+ : (sunflower.activeRouteDetail?.summary || sunflower.routeStory || sunflower.bootstrapFocus || null);
174
188
  const checkpointFocus = sunflower.activeTicket
175
189
  ? `Keep the board packet honest around ${sunflower.activeTicket.ticketId} while preserving the open-problem / active-route / route-breakthrough ladder.`
176
- : (sunflower.checkpointFocus || null);
190
+ : (sunflower.activeRouteDetail?.whyNow || sunflower.checkpointFocus || null);
177
191
  return {
178
192
  familyRole: sunflower.familyRole,
179
193
  harnessProfile: sunflower.harnessProfile,
@@ -187,11 +201,54 @@ function deriveProblemSummary(problem) {
187
201
  },
188
202
  routeStory,
189
203
  checkpointFocus,
190
- nextHonestMove: sunflower.nextHonestMove || sunflower.computeNextAction || 'Refresh the active route and package a new honest checkpoint.',
204
+ nextHonestMove:
205
+ sunflower.activeAtomDetail?.nextMove
206
+ || sunflower.activeTicketDetail?.nextMove
207
+ || sunflower.nextHonestMove
208
+ || sunflower.computeNextAction
209
+ || 'Refresh the active route and package a new honest checkpoint.',
210
+ packArtifacts: {
211
+ frontierNotePath: sunflower.frontierNotePath,
212
+ routeHistoryPath: sunflower.routeHistoryPath,
213
+ checkpointTemplatePath: sunflower.checkpointTemplatePath,
214
+ reportTemplatePath: sunflower.reportTemplatePath,
215
+ },
216
+ activeTicketId: sunflower.activeTicket?.ticketId ?? null,
217
+ activeAtomId: sunflower.firstReadyAtom?.atomId ?? null,
191
218
  questionLedger: sunflower.questionLedger,
192
219
  };
193
220
  }
194
221
 
222
+ if (problem.cluster === 'number-theory') {
223
+ const snapshot = buildNumberTheoryStatusSnapshot(problem);
224
+ return {
225
+ familyRole: snapshot.familyRole,
226
+ harnessProfile: snapshot.harnessProfile,
227
+ activeRoute: snapshot.activeRoute,
228
+ routeBreakthrough: snapshot.routeBreakthrough,
229
+ problemSolved: snapshot.problemSolved,
230
+ openProblem: snapshot.openProblem,
231
+ currentFrontier: {
232
+ kind: snapshot.firstReadyAtom ? 'ready_atom' : 'route_frontier',
233
+ detail: snapshot.firstReadyAtom
234
+ ? `${snapshot.firstReadyAtom.atom_id} — ${snapshot.firstReadyAtom.title}`
235
+ : snapshot.frontierDetail,
236
+ },
237
+ routeStory: snapshot.activeRouteDetail?.summary || snapshot.routeStory,
238
+ checkpointFocus: snapshot.checkpointFocus,
239
+ nextHonestMove: snapshot.nextHonestMove,
240
+ packArtifacts: {
241
+ frontierNotePath: snapshot.frontierNotePath,
242
+ routeHistoryPath: snapshot.routeHistoryPath,
243
+ checkpointTemplatePath: snapshot.checkpointTemplatePath,
244
+ reportTemplatePath: snapshot.reportTemplatePath,
245
+ },
246
+ activeTicketId: snapshot.activeTicketDetail?.ticket_id ?? null,
247
+ activeAtomId: snapshot.firstReadyAtom?.atom_id ?? null,
248
+ questionLedger: snapshot.questionLedger,
249
+ };
250
+ }
251
+
195
252
  return deriveGenericProblemSummary(problem);
196
253
  }
197
254
 
@@ -273,6 +330,9 @@ export function syncState(workspaceRoot = getWorkspaceRoot()) {
273
330
  routeStory: summary.routeStory,
274
331
  checkpointFocus: summary.checkpointFocus,
275
332
  nextHonestMove: summary.nextHonestMove,
333
+ packArtifacts: summary.packArtifacts,
334
+ activeTicketId: summary.activeTicketId,
335
+ activeAtomId: summary.activeAtomId,
276
336
  lastCheckpointSyncAt: existing.lastCheckpointSyncAt ?? null,
277
337
  };
278
338