erdos-problems 0.1.13 → 0.2.0
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 +77 -4
- package/docs/RESEARCH_LOOP.md +14 -2
- package/package.json +1 -1
- package/packs/number-theory/README.md +13 -0
- package/packs/number-theory/problems/1/CONTEXT.md +8 -0
- package/packs/number-theory/problems/1/context.yaml +25 -0
- package/packs/number-theory/problems/2/CONTEXT.md +8 -0
- package/packs/number-theory/problems/2/context.yaml +25 -0
- package/packs/sunflower/README.md +17 -4
- package/packs/sunflower/problems/20/CHECKPOINT_TEMPLATE.md +29 -0
- package/packs/sunflower/problems/20/FRONTIER_NOTE.md +13 -0
- package/packs/sunflower/problems/20/OPS_DETAILS.yaml +44 -0
- package/packs/sunflower/problems/20/REPORT_TEMPLATE.md +23 -0
- package/packs/sunflower/problems/20/ROUTE_HISTORY.md +18 -0
- package/packs/sunflower/problems/536/OPS_DETAILS.yaml +39 -0
- package/packs/sunflower/problems/856/OPS_DETAILS.yaml +39 -0
- package/packs/sunflower/problems/857/CHECKPOINT_TEMPLATE.md +32 -0
- package/packs/sunflower/problems/857/FRONTIER_NOTE.md +18 -0
- package/packs/sunflower/problems/857/OPS_DETAILS.yaml +65 -0
- package/packs/sunflower/problems/857/REPORT_TEMPLATE.md +26 -0
- package/packs/sunflower/problems/857/ROUTE_HISTORY.md +25 -0
- package/src/cli/index.js +14 -2
- package/src/commands/archive.js +46 -0
- package/src/commands/maintainer.js +20 -2
- package/src/commands/problem.js +3 -0
- package/src/commands/pull.js +127 -4
- package/src/commands/sunflower.js +290 -12
- package/src/commands/upstream.js +129 -0
- package/src/commands/workspace.js +4 -0
- package/src/runtime/archive.js +87 -0
- package/src/runtime/checkpoints.js +27 -0
- package/src/runtime/maintainer-seed.js +70 -0
- package/src/runtime/paths.js +16 -0
- package/src/runtime/state.js +32 -3
- package/src/runtime/sunflower.js +329 -2
- package/src/runtime/workspace.js +4 -0
- package/src/upstream/literature.js +83 -0
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { getProblem } from '../atlas/catalog.js';
|
|
2
2
|
import { getWorkspaceRoot } from '../runtime/paths.js';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
buildSunflowerStatusSnapshot,
|
|
5
|
+
getSunflowerAtomSnapshot,
|
|
6
|
+
getSunflowerRouteSnapshot,
|
|
7
|
+
getSunflowerTicketSnapshot,
|
|
8
|
+
runSunflowerLocalScout,
|
|
9
|
+
writeSunflowerStatusRecord,
|
|
10
|
+
} from '../runtime/sunflower.js';
|
|
4
11
|
import { readCurrentProblem } from '../runtime/workspace.js';
|
|
5
12
|
|
|
6
13
|
function parseStatusArgs(args) {
|
|
@@ -45,6 +52,53 @@ function parseTicketsArgs(args) {
|
|
|
45
52
|
return parseStatusArgs(args);
|
|
46
53
|
}
|
|
47
54
|
|
|
55
|
+
function parseFrontierArgs(args) {
|
|
56
|
+
return parseStatusArgs(args);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function parseEntityArgs(args, entityLabel) {
|
|
60
|
+
const parsed = {
|
|
61
|
+
problemId: null,
|
|
62
|
+
entityId: null,
|
|
63
|
+
asJson: false,
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
67
|
+
const token = args[index];
|
|
68
|
+
if (token === '--json') {
|
|
69
|
+
parsed.asJson = true;
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
if (!parsed.problemId) {
|
|
73
|
+
parsed.problemId = token;
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
if (!parsed.entityId) {
|
|
77
|
+
parsed.entityId = token;
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
return { error: `Unknown sunflower ${entityLabel} option: ${token}` };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return parsed;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function parseComputeArgs(args) {
|
|
87
|
+
const [computeCommand, ...rest] = args;
|
|
88
|
+
if (!computeCommand || computeCommand === 'help' || computeCommand === '--help') {
|
|
89
|
+
return { help: true };
|
|
90
|
+
}
|
|
91
|
+
if (computeCommand !== 'run') {
|
|
92
|
+
return { error: `Unknown sunflower compute subcommand: ${computeCommand}` };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const parsed = parseStatusArgs(rest);
|
|
96
|
+
return {
|
|
97
|
+
...parsed,
|
|
98
|
+
computeCommand,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
48
102
|
function getBoard(snapshot) {
|
|
49
103
|
return snapshot.atomicBoardSummary;
|
|
50
104
|
}
|
|
@@ -91,6 +145,24 @@ function ticketProgressLabel(ticket, snapshot) {
|
|
|
91
145
|
return 'open';
|
|
92
146
|
}
|
|
93
147
|
|
|
148
|
+
function resolveSunflowerProblem(problemId) {
|
|
149
|
+
const resolvedProblemId = problemId ?? readCurrentProblem();
|
|
150
|
+
if (!resolvedProblemId) {
|
|
151
|
+
return { error: 'Missing problem id and no active problem is selected.' };
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const problem = getProblem(resolvedProblemId);
|
|
155
|
+
if (!problem) {
|
|
156
|
+
return { error: `Unknown problem: ${resolvedProblemId}` };
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (problem.cluster !== 'sunflower') {
|
|
160
|
+
return { error: `Problem ${problem.problemId} is not in the sunflower harness.` };
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return { problem };
|
|
164
|
+
}
|
|
165
|
+
|
|
94
166
|
function printSunflowerStatus(snapshot, registryPaths) {
|
|
95
167
|
console.log(`${snapshot.displayName} sunflower harness`);
|
|
96
168
|
console.log(`Title: ${snapshot.title}`);
|
|
@@ -140,6 +212,10 @@ function printSunflowerStatus(snapshot, registryPaths) {
|
|
|
140
212
|
console.log(`Agent start packet: ${snapshot.agentStartPresent ? snapshot.agentStartPath : '(missing)'}`);
|
|
141
213
|
console.log(`Checkpoint packet: ${snapshot.checkpointPacketPresent ? snapshot.checkpointPacketPath : '(missing)'}`);
|
|
142
214
|
console.log(`Report packet: ${snapshot.reportPacketPresent ? snapshot.reportPacketPath : '(missing)'}`);
|
|
215
|
+
console.log(`Frontier note: ${snapshot.frontierNotePresent ? snapshot.frontierNotePath : '(missing)'}`);
|
|
216
|
+
console.log(`Route history: ${snapshot.routeHistoryPresent ? snapshot.routeHistoryPath : '(missing)'}`);
|
|
217
|
+
console.log(`Checkpoint template: ${snapshot.checkpointTemplatePresent ? snapshot.checkpointTemplatePath : '(missing)'}`);
|
|
218
|
+
console.log(`Report template: ${snapshot.reportTemplatePresent ? snapshot.reportTemplatePath : '(missing)'}`);
|
|
143
219
|
console.log(`Compute lane present: ${snapshot.computeLanePresent ? 'yes' : 'no'}`);
|
|
144
220
|
console.log(`Compute lane count: ${snapshot.computeLaneCount}`);
|
|
145
221
|
console.log(`Compute summary: ${snapshot.computeSummary}`);
|
|
@@ -368,6 +444,124 @@ function printSunflowerTickets(snapshot) {
|
|
|
368
444
|
}
|
|
369
445
|
}
|
|
370
446
|
|
|
447
|
+
function printSunflowerFrontier(snapshot) {
|
|
448
|
+
console.log(`${snapshot.displayName} sunflower frontier`);
|
|
449
|
+
console.log(`Active route: ${snapshot.activeRoute ?? '(none)'}`);
|
|
450
|
+
console.log(`Active ticket: ${snapshot.activeTicket?.ticketId ?? '(none)'}`);
|
|
451
|
+
console.log(`Frontier label: ${snapshot.frontierLabel ?? '(none)'}`);
|
|
452
|
+
console.log(`Frontier detail: ${snapshot.frontierDetail ?? '(none)'}`);
|
|
453
|
+
console.log(`Checkpoint focus: ${snapshot.checkpointFocus ?? '(none)'}`);
|
|
454
|
+
console.log(`Next honest move: ${snapshot.nextHonestMove}`);
|
|
455
|
+
console.log(`Ready atoms: ${snapshot.readyAtomCount}`);
|
|
456
|
+
console.log(`Mirage frontiers: ${snapshot.mirageFrontierCount}`);
|
|
457
|
+
if (snapshot.firstReadyAtom) {
|
|
458
|
+
console.log(`First ready atom: ${snapshot.firstReadyAtom.atomId} — ${snapshot.firstReadyAtom.title}`);
|
|
459
|
+
}
|
|
460
|
+
if (snapshot.activeRouteDetail) {
|
|
461
|
+
console.log(`Route focus: ${snapshot.activeRouteDetail.title ?? snapshot.activeRouteDetail.routeId}`);
|
|
462
|
+
console.log(`Route why now: ${snapshot.activeRouteDetail.whyNow ?? '(none)'}`);
|
|
463
|
+
}
|
|
464
|
+
if (snapshot.activeTicketDetail) {
|
|
465
|
+
console.log(`Ticket focus: ${snapshot.activeTicketDetail.title ?? snapshot.activeTicketDetail.ticketId}`);
|
|
466
|
+
console.log(`Ticket blocker: ${snapshot.activeTicketDetail.currentBlocker ?? '(none)'}`);
|
|
467
|
+
}
|
|
468
|
+
if (snapshot.activeAtomDetail) {
|
|
469
|
+
console.log(`Atom focus: ${snapshot.activeAtomDetail.title ?? snapshot.activeAtomDetail.atomId}`);
|
|
470
|
+
console.log(`Atom why now: ${snapshot.activeAtomDetail.whyNow ?? '(none)'}`);
|
|
471
|
+
}
|
|
472
|
+
console.log(`Frontier note: ${snapshot.frontierNotePresent ? snapshot.frontierNotePath : '(missing)'}`);
|
|
473
|
+
console.log(`Route history: ${snapshot.routeHistoryPresent ? snapshot.routeHistoryPath : '(missing)'}`);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
function printSunflowerRouteDetail(routeSnapshot) {
|
|
477
|
+
const detail = routeSnapshot.routeDetail;
|
|
478
|
+
const boardRoute = routeSnapshot.boardRoute;
|
|
479
|
+
|
|
480
|
+
console.log(`${routeSnapshot.displayName} sunflower route ${routeSnapshot.routeId}`);
|
|
481
|
+
console.log(`Active route: ${routeSnapshot.activeRoute ?? '(none)'}`);
|
|
482
|
+
if (detail) {
|
|
483
|
+
console.log(`Title: ${detail.title ?? '(none)'}`);
|
|
484
|
+
console.log(`Status: ${detail.status ?? '(none)'}`);
|
|
485
|
+
console.log(`Summary: ${detail.summary ?? '(none)'}`);
|
|
486
|
+
console.log(`Why now: ${detail.whyNow ?? '(none)'}`);
|
|
487
|
+
console.log(`Next move: ${detail.nextMove ?? '(none)'}`);
|
|
488
|
+
console.log(`Theorem module: ${detail.theoremModule ?? '(none)'}`);
|
|
489
|
+
console.log(`Ticket ids: ${detail.ticketIds.join(', ') || '(none)'}`);
|
|
490
|
+
}
|
|
491
|
+
if (boardRoute) {
|
|
492
|
+
console.log(`Loose progress: ${boardRoute.looseDone}/${boardRoute.looseTotal}`);
|
|
493
|
+
console.log(`Strict progress: ${boardRoute.strictDone}/${boardRoute.strictTotal}`);
|
|
494
|
+
}
|
|
495
|
+
if (routeSnapshot.firstReadyAtom) {
|
|
496
|
+
console.log(`First ready atom: ${routeSnapshot.firstReadyAtom.atomId} — ${routeSnapshot.firstReadyAtom.title}`);
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
function printSunflowerTicketDetail(ticketSnapshot) {
|
|
501
|
+
const detail = ticketSnapshot.ticketDetail;
|
|
502
|
+
const boardTicket = ticketSnapshot.boardTicket;
|
|
503
|
+
|
|
504
|
+
console.log(`${ticketSnapshot.displayName} sunflower ticket ${ticketSnapshot.ticketId}`);
|
|
505
|
+
console.log(`Active ticket: ${ticketSnapshot.activeTicketId ?? '(none)'}`);
|
|
506
|
+
if (detail) {
|
|
507
|
+
console.log(`Title: ${detail.title ?? '(none)'}`);
|
|
508
|
+
console.log(`Route: ${detail.routeId ?? '(none)'}`);
|
|
509
|
+
console.log(`Status: ${detail.status ?? '(none)'}`);
|
|
510
|
+
console.log(`Summary: ${detail.summary ?? '(none)'}`);
|
|
511
|
+
console.log(`Gate story: ${detail.gateStory ?? '(none)'}`);
|
|
512
|
+
console.log(`Current blocker: ${detail.currentBlocker ?? '(none)'}`);
|
|
513
|
+
console.log(`Next move: ${detail.nextMove ?? '(none)'}`);
|
|
514
|
+
console.log(`Atom ids: ${detail.atomIds.join(', ') || '(none)'}`);
|
|
515
|
+
}
|
|
516
|
+
if (boardTicket) {
|
|
517
|
+
console.log(`Leaf theorem: ${boardTicket.routeLeaf ?? '(none)'}`);
|
|
518
|
+
console.log(`Leaf status: ${boardTicket.leafStatus ?? '(none)'}`);
|
|
519
|
+
console.log(`Gate progress: ${boardTicket.gatesDone}/${boardTicket.gatesTotal}`);
|
|
520
|
+
console.log(`Atom progress: ${boardTicket.atomsDone}/${boardTicket.atomsTotal}`);
|
|
521
|
+
}
|
|
522
|
+
if (ticketSnapshot.firstReadyAtom?.ticketId === ticketSnapshot.ticketId) {
|
|
523
|
+
console.log(`First ready atom: ${ticketSnapshot.firstReadyAtom.atomId} — ${ticketSnapshot.firstReadyAtom.title}`);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
function printSunflowerAtomDetail(atomSnapshot) {
|
|
528
|
+
const detail = atomSnapshot.atomDetail;
|
|
529
|
+
const boardAtom = atomSnapshot.boardAtom;
|
|
530
|
+
|
|
531
|
+
console.log(`${atomSnapshot.displayName} sunflower atom ${atomSnapshot.atomId}`);
|
|
532
|
+
if (detail) {
|
|
533
|
+
console.log(`Title: ${detail.title ?? '(none)'}`);
|
|
534
|
+
console.log(`Route: ${detail.routeId ?? '(none)'}`);
|
|
535
|
+
console.log(`Ticket: ${detail.ticketId ?? '(none)'}`);
|
|
536
|
+
console.log(`Gate: ${detail.gateId ?? '(none)'}`);
|
|
537
|
+
console.log(`Tier: ${detail.tier ?? '(none)'}`);
|
|
538
|
+
console.log(`Kind: ${detail.kind ?? '(none)'}`);
|
|
539
|
+
console.log(`Status: ${detail.status ?? '(none)'}`);
|
|
540
|
+
console.log(`Summary: ${detail.summary ?? '(none)'}`);
|
|
541
|
+
console.log(`Why now: ${detail.whyNow ?? '(none)'}`);
|
|
542
|
+
console.log(`Next move: ${detail.nextMove ?? '(none)'}`);
|
|
543
|
+
console.log(`Dependencies: ${detail.dependencies.join(', ') || '(none)'}`);
|
|
544
|
+
console.log(`Verification hook: ${detail.verificationHook.join(' | ') || '(none)'}`);
|
|
545
|
+
}
|
|
546
|
+
if (boardAtom) {
|
|
547
|
+
console.log(`Board queue status: ${boardAtom.status ?? '(none)'}`);
|
|
548
|
+
}
|
|
549
|
+
if (atomSnapshot.firstReadyAtom?.atomId === atomSnapshot.atomId) {
|
|
550
|
+
console.log('Current frontier atom: yes');
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
function printSunflowerComputeRun(result) {
|
|
555
|
+
console.log(`Sunflower local scout run created for problem ${result.snapshot.problemId}`);
|
|
556
|
+
console.log(`Run id: ${result.runId}`);
|
|
557
|
+
console.log(`Run dir: ${result.runDir}`);
|
|
558
|
+
console.log(`Lane: ${result.snapshot.activePacket?.laneId ?? '(none)'}`);
|
|
559
|
+
console.log(`Dispatch action: ${result.snapshot.computeGovernance?.dispatchResult.action ?? '(none)'}`);
|
|
560
|
+
console.log(`Selected rung: ${result.snapshot.computeGovernance?.selectedRung?.label ?? '(none)'}`);
|
|
561
|
+
console.log(`Current frontier: ${result.runRecord.currentFrontier}`);
|
|
562
|
+
console.log(`Run summary: ${result.runRecord.artifacts.runSummaryPath}`);
|
|
563
|
+
}
|
|
564
|
+
|
|
371
565
|
export function runSunflowerCommand(args) {
|
|
372
566
|
const [subcommand, ...rest] = args;
|
|
373
567
|
|
|
@@ -379,10 +573,15 @@ export function runSunflowerCommand(args) {
|
|
|
379
573
|
console.log(' erdos sunflower ladder [<id>] [--json]');
|
|
380
574
|
console.log(' erdos sunflower routes [<id>] [--json]');
|
|
381
575
|
console.log(' erdos sunflower tickets [<id>] [--json]');
|
|
576
|
+
console.log(' erdos sunflower frontier [<id>] [--json]');
|
|
577
|
+
console.log(' erdos sunflower route <problem-id> <route-id> [--json]');
|
|
578
|
+
console.log(' erdos sunflower ticket <problem-id> <ticket-id> [--json]');
|
|
579
|
+
console.log(' erdos sunflower atom <problem-id> <atom-id> [--json]');
|
|
580
|
+
console.log(' erdos sunflower compute run [<id>] [--json]');
|
|
382
581
|
return 0;
|
|
383
582
|
}
|
|
384
583
|
|
|
385
|
-
if (!['status', 'board', 'ready', 'ladder', 'routes', 'tickets'].includes(subcommand)) {
|
|
584
|
+
if (!['status', 'board', 'ready', 'ladder', 'routes', 'tickets', 'frontier', 'route', 'ticket', 'atom', 'compute'].includes(subcommand)) {
|
|
386
585
|
console.error(`Unknown sunflower subcommand: ${subcommand}`);
|
|
387
586
|
return 1;
|
|
388
587
|
}
|
|
@@ -398,29 +597,103 @@ export function runSunflowerCommand(args) {
|
|
|
398
597
|
parsed = parseRoutesArgs(rest);
|
|
399
598
|
} else if (subcommand === 'tickets') {
|
|
400
599
|
parsed = parseTicketsArgs(rest);
|
|
600
|
+
} else if (subcommand === 'frontier') {
|
|
601
|
+
parsed = parseFrontierArgs(rest);
|
|
602
|
+
} else if (subcommand === 'route') {
|
|
603
|
+
parsed = parseEntityArgs(rest, 'route');
|
|
604
|
+
} else if (subcommand === 'ticket') {
|
|
605
|
+
parsed = parseEntityArgs(rest, 'ticket');
|
|
606
|
+
} else if (subcommand === 'atom') {
|
|
607
|
+
parsed = parseEntityArgs(rest, 'atom');
|
|
608
|
+
} else if (subcommand === 'compute') {
|
|
609
|
+
parsed = parseComputeArgs(rest);
|
|
401
610
|
} else {
|
|
402
611
|
parsed = parseStatusArgs(rest);
|
|
403
612
|
}
|
|
613
|
+
|
|
614
|
+
if (parsed?.help) {
|
|
615
|
+
console.log('Usage:');
|
|
616
|
+
console.log(' erdos sunflower compute run [<id>] [--json]');
|
|
617
|
+
return 0;
|
|
618
|
+
}
|
|
404
619
|
if (parsed.error) {
|
|
405
620
|
console.error(parsed.error);
|
|
406
621
|
return 1;
|
|
407
622
|
}
|
|
408
623
|
|
|
409
|
-
const
|
|
410
|
-
if (
|
|
411
|
-
console.error(
|
|
624
|
+
const { problem, error } = resolveSunflowerProblem(parsed.problemId);
|
|
625
|
+
if (error) {
|
|
626
|
+
console.error(error);
|
|
412
627
|
return 1;
|
|
413
628
|
}
|
|
414
629
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
630
|
+
if (subcommand === 'route') {
|
|
631
|
+
if (!parsed.entityId) {
|
|
632
|
+
console.error('Missing route id.');
|
|
633
|
+
return 1;
|
|
634
|
+
}
|
|
635
|
+
const routeSnapshot = getSunflowerRouteSnapshot(problem, parsed.entityId);
|
|
636
|
+
if (!routeSnapshot) {
|
|
637
|
+
console.error(`Unknown sunflower route: ${parsed.entityId}`);
|
|
638
|
+
return 1;
|
|
639
|
+
}
|
|
640
|
+
if (parsed.asJson) {
|
|
641
|
+
console.log(JSON.stringify(routeSnapshot, null, 2));
|
|
642
|
+
return 0;
|
|
643
|
+
}
|
|
644
|
+
printSunflowerRouteDetail(routeSnapshot);
|
|
645
|
+
return 0;
|
|
419
646
|
}
|
|
420
647
|
|
|
421
|
-
if (
|
|
422
|
-
|
|
423
|
-
|
|
648
|
+
if (subcommand === 'ticket') {
|
|
649
|
+
if (!parsed.entityId) {
|
|
650
|
+
console.error('Missing ticket id.');
|
|
651
|
+
return 1;
|
|
652
|
+
}
|
|
653
|
+
const ticketSnapshot = getSunflowerTicketSnapshot(problem, parsed.entityId);
|
|
654
|
+
if (!ticketSnapshot) {
|
|
655
|
+
console.error(`Unknown sunflower ticket: ${parsed.entityId}`);
|
|
656
|
+
return 1;
|
|
657
|
+
}
|
|
658
|
+
if (parsed.asJson) {
|
|
659
|
+
console.log(JSON.stringify(ticketSnapshot, null, 2));
|
|
660
|
+
return 0;
|
|
661
|
+
}
|
|
662
|
+
printSunflowerTicketDetail(ticketSnapshot);
|
|
663
|
+
return 0;
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
if (subcommand === 'atom') {
|
|
667
|
+
if (!parsed.entityId) {
|
|
668
|
+
console.error('Missing atom id.');
|
|
669
|
+
return 1;
|
|
670
|
+
}
|
|
671
|
+
const atomSnapshot = getSunflowerAtomSnapshot(problem, parsed.entityId);
|
|
672
|
+
if (!atomSnapshot) {
|
|
673
|
+
console.error(`Unknown sunflower atom: ${parsed.entityId}`);
|
|
674
|
+
return 1;
|
|
675
|
+
}
|
|
676
|
+
if (parsed.asJson) {
|
|
677
|
+
console.log(JSON.stringify(atomSnapshot, null, 2));
|
|
678
|
+
return 0;
|
|
679
|
+
}
|
|
680
|
+
printSunflowerAtomDetail(atomSnapshot);
|
|
681
|
+
return 0;
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
if (subcommand === 'compute') {
|
|
685
|
+
try {
|
|
686
|
+
const result = runSunflowerLocalScout(problem, getWorkspaceRoot());
|
|
687
|
+
if (parsed.asJson) {
|
|
688
|
+
console.log(JSON.stringify(result, null, 2));
|
|
689
|
+
return 0;
|
|
690
|
+
}
|
|
691
|
+
printSunflowerComputeRun(result);
|
|
692
|
+
return 0;
|
|
693
|
+
} catch (runError) {
|
|
694
|
+
console.error(String(runError.message ?? runError));
|
|
695
|
+
return 1;
|
|
696
|
+
}
|
|
424
697
|
}
|
|
425
698
|
|
|
426
699
|
const snapshot = buildSunflowerStatusSnapshot(problem);
|
|
@@ -456,6 +729,11 @@ export function runSunflowerCommand(args) {
|
|
|
456
729
|
return 0;
|
|
457
730
|
}
|
|
458
731
|
|
|
732
|
+
if (subcommand === 'frontier') {
|
|
733
|
+
printSunflowerFrontier(snapshot);
|
|
734
|
+
return 0;
|
|
735
|
+
}
|
|
736
|
+
|
|
459
737
|
printSunflowerStatus(snapshot, registryPaths);
|
|
460
738
|
return 0;
|
|
461
739
|
}
|
package/src/commands/upstream.js
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
|
+
import { getProblem } from '../atlas/catalog.js';
|
|
2
|
+
import { fetchProblemSiteSnapshot } from '../upstream/site.js';
|
|
1
3
|
import { buildUpstreamDiff, loadActiveUpstreamSnapshot, syncUpstream, writeDiffArtifacts } from '../upstream/sync.js';
|
|
2
4
|
|
|
5
|
+
function parseDriftArgs(args) {
|
|
6
|
+
const parsed = {
|
|
7
|
+
problemId: null,
|
|
8
|
+
includeSite: false,
|
|
9
|
+
asJson: false,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
13
|
+
const token = args[index];
|
|
14
|
+
if (token === '--include-site') {
|
|
15
|
+
parsed.includeSite = true;
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
if (token === '--json') {
|
|
19
|
+
parsed.asJson = true;
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
if (!parsed.problemId) {
|
|
23
|
+
parsed.problemId = token;
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
return { error: `Unknown upstream drift option: ${token}` };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return parsed;
|
|
30
|
+
}
|
|
31
|
+
|
|
3
32
|
export async function runUpstreamCommand(args) {
|
|
4
33
|
const [subcommand, ...rest] = args;
|
|
5
34
|
|
|
@@ -8,6 +37,7 @@ export async function runUpstreamCommand(args) {
|
|
|
8
37
|
console.log(' erdos upstream show');
|
|
9
38
|
console.log(' erdos upstream sync [--write-package-snapshot]');
|
|
10
39
|
console.log(' erdos upstream diff [--write-package-report]');
|
|
40
|
+
console.log(' erdos upstream drift [<id>] [--include-site] [--json]');
|
|
11
41
|
return 0;
|
|
12
42
|
}
|
|
13
43
|
|
|
@@ -55,6 +85,105 @@ export async function runUpstreamCommand(args) {
|
|
|
55
85
|
return 0;
|
|
56
86
|
}
|
|
57
87
|
|
|
88
|
+
if (subcommand === 'drift') {
|
|
89
|
+
const parsed = parseDriftArgs(rest);
|
|
90
|
+
if (parsed.error) {
|
|
91
|
+
console.error(parsed.error);
|
|
92
|
+
return 1;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const diff = buildUpstreamDiff();
|
|
96
|
+
if (!parsed.problemId) {
|
|
97
|
+
const statusDrifts = diff.overlaps.filter((row) => !row.statusMatches);
|
|
98
|
+
const formalizationDrifts = diff.overlaps.filter((row) => !row.formalizedMatches);
|
|
99
|
+
const tagDrifts = diff.overlaps.filter((row) => row.localOnlyTags.length > 0 || row.upstreamOnlyTags.length > 0);
|
|
100
|
+
const payload = {
|
|
101
|
+
localProblemCount: diff.localProblemCount,
|
|
102
|
+
upstreamProblemCount: diff.upstreamProblemCount,
|
|
103
|
+
statusDriftCount: statusDrifts.length,
|
|
104
|
+
formalizationDriftCount: formalizationDrifts.length,
|
|
105
|
+
tagDriftCount: tagDrifts.length,
|
|
106
|
+
statusDrifts: statusDrifts.slice(0, 10),
|
|
107
|
+
formalizationDrifts: formalizationDrifts.slice(0, 10),
|
|
108
|
+
tagDrifts: tagDrifts.slice(0, 10),
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
if (parsed.asJson) {
|
|
112
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
113
|
+
return 0;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
console.log('Upstream drift dashboard');
|
|
117
|
+
console.log(`Local seeded problems: ${payload.localProblemCount}`);
|
|
118
|
+
console.log(`Upstream total problems: ${payload.upstreamProblemCount}`);
|
|
119
|
+
console.log(`Site-status drifts: ${payload.statusDriftCount}`);
|
|
120
|
+
console.log(`Formalization drifts: ${payload.formalizationDriftCount}`);
|
|
121
|
+
console.log(`Tag drifts: ${payload.tagDriftCount}`);
|
|
122
|
+
return 0;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const problem = getProblem(parsed.problemId);
|
|
126
|
+
const snapshot = loadActiveUpstreamSnapshot();
|
|
127
|
+
const upstreamRecord = snapshot?.index?.by_number?.[String(parsed.problemId)] ?? null;
|
|
128
|
+
if (!problem && !upstreamRecord) {
|
|
129
|
+
console.error(`Unknown problem: ${parsed.problemId}`);
|
|
130
|
+
return 1;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
let siteSnapshot = null;
|
|
134
|
+
let siteError = null;
|
|
135
|
+
if (parsed.includeSite) {
|
|
136
|
+
try {
|
|
137
|
+
siteSnapshot = await fetchProblemSiteSnapshot(parsed.problemId);
|
|
138
|
+
} catch (error) {
|
|
139
|
+
siteError = String(error.message ?? error);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const payload = {
|
|
144
|
+
problemId: String(parsed.problemId),
|
|
145
|
+
local: problem
|
|
146
|
+
? {
|
|
147
|
+
siteStatus: problem.siteStatus,
|
|
148
|
+
repoStatus: problem.repoStatus,
|
|
149
|
+
title: problem.title,
|
|
150
|
+
}
|
|
151
|
+
: null,
|
|
152
|
+
upstream: upstreamRecord
|
|
153
|
+
? {
|
|
154
|
+
siteStatus: upstreamRecord.status?.state ?? null,
|
|
155
|
+
formalizedState: upstreamRecord.formalized?.state ?? null,
|
|
156
|
+
tags: upstreamRecord.tags ?? [],
|
|
157
|
+
}
|
|
158
|
+
: null,
|
|
159
|
+
site: siteSnapshot
|
|
160
|
+
? {
|
|
161
|
+
siteStatus: siteSnapshot.siteStatus,
|
|
162
|
+
statusLine: siteSnapshot.siteStatusRaw,
|
|
163
|
+
title: siteSnapshot.title,
|
|
164
|
+
}
|
|
165
|
+
: null,
|
|
166
|
+
siteError,
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
if (parsed.asJson) {
|
|
170
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
171
|
+
return 0;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
console.log(`Upstream drift for problem ${parsed.problemId}`);
|
|
175
|
+
console.log(`Local site status: ${payload.local?.siteStatus ?? '(none)'}`);
|
|
176
|
+
console.log(`Upstream site status: ${payload.upstream?.siteStatus ?? '(none)'}`);
|
|
177
|
+
console.log(`Site snapshot status: ${payload.site?.siteStatus ?? '(not fetched)'}`);
|
|
178
|
+
console.log(`Local repo status: ${payload.local?.repoStatus ?? '(none)'}`);
|
|
179
|
+
console.log(`Upstream formalized state: ${payload.upstream?.formalizedState ?? '(none)'}`);
|
|
180
|
+
console.log(`Upstream tags: ${payload.upstream?.tags?.join(', ') || '(none)'}`);
|
|
181
|
+
if (siteError) {
|
|
182
|
+
console.log(`Site fetch note: ${siteError}`);
|
|
183
|
+
}
|
|
184
|
+
return 0;
|
|
185
|
+
}
|
|
186
|
+
|
|
58
187
|
console.error(`Unknown upstream subcommand: ${subcommand}`);
|
|
59
188
|
return 1;
|
|
60
189
|
}
|
|
@@ -38,6 +38,8 @@ export function runWorkspaceCommand(args) {
|
|
|
38
38
|
console.log(`Workspace pull dir: ${summary.pullDir}`);
|
|
39
39
|
console.log(`Workspace artifact dir: ${summary.artifactDir}`);
|
|
40
40
|
console.log(`Workspace literature dir: ${summary.literatureDir}`);
|
|
41
|
+
console.log(`Workspace runs dir: ${summary.runsDir}`);
|
|
42
|
+
console.log(`Workspace archives dir: ${summary.archivesDir}`);
|
|
41
43
|
console.log(`Active seeded dossier dir: ${summary.seededProblemDir}`);
|
|
42
44
|
console.log(`Preferred agent: ${config.preferredAgent}`);
|
|
43
45
|
console.log(`Continuation mode: ${summary.continuationMode ?? config.continuation}`);
|
|
@@ -58,6 +60,8 @@ export function runWorkspaceCommand(args) {
|
|
|
58
60
|
console.log(`Sunflower harness profile: ${sunflower.harnessProfile ?? '(none)'}`);
|
|
59
61
|
console.log(`Sunflower route: ${sunflower.activeRoute ?? '(none)'}`);
|
|
60
62
|
console.log(`Sunflower frontier: ${sunflower.frontierDetail ?? '(none)'}`);
|
|
63
|
+
console.log(`Sunflower frontier note: ${sunflower.frontierNotePath ?? '(none)'}`);
|
|
64
|
+
console.log(`Sunflower route history: ${sunflower.routeHistoryPath ?? '(none)'}`);
|
|
61
65
|
console.log(`Sunflower board: ${sunflower.atomicBoardPresent ? 'yes' : 'no'}`);
|
|
62
66
|
if (sunflower.atomicBoardSummary) {
|
|
63
67
|
console.log(`Sunflower board title: ${sunflower.atomicBoardSummary.boardTitle ?? '(none)'}`);
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { getProblem } from '../atlas/catalog.js';
|
|
3
|
+
import { ensureDir, writeJson, writeText } from './files.js';
|
|
4
|
+
import { getWorkspaceArchiveDir, getWorkspaceRoot } from './paths.js';
|
|
5
|
+
|
|
6
|
+
function isSolved(problem) {
|
|
7
|
+
return String(problem?.siteStatus ?? '').toLowerCase() === 'solved'
|
|
8
|
+
|| Boolean(problem?.researchState?.problem_solved);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function getArchiveView(problemId) {
|
|
12
|
+
const problem = getProblem(problemId);
|
|
13
|
+
if (!problem) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return {
|
|
18
|
+
problemId: problem.problemId,
|
|
19
|
+
displayName: problem.displayName,
|
|
20
|
+
title: problem.title,
|
|
21
|
+
siteStatus: problem.siteStatus,
|
|
22
|
+
repoStatus: problem.repoStatus,
|
|
23
|
+
solved: isSolved(problem),
|
|
24
|
+
archiveMode: isSolved(problem) ? 'method_exemplar' : 'inactive',
|
|
25
|
+
nextMove: isSolved(problem)
|
|
26
|
+
? 'Extract reusable methods, references, and formalization hooks without treating this as an open-problem cockpit.'
|
|
27
|
+
: 'This problem is not currently in solved archival mode.',
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function scaffoldArchive(problemId, workspaceRoot = getWorkspaceRoot()) {
|
|
32
|
+
const problem = getProblem(problemId);
|
|
33
|
+
if (!problem) {
|
|
34
|
+
throw new Error(`Unknown problem: ${problemId}`);
|
|
35
|
+
}
|
|
36
|
+
if (!isSolved(problem)) {
|
|
37
|
+
throw new Error(`Problem ${problemId} is not solved, so archival mode is not active.`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const archiveDir = getWorkspaceArchiveDir(problemId, workspaceRoot);
|
|
41
|
+
ensureDir(archiveDir);
|
|
42
|
+
|
|
43
|
+
const payload = {
|
|
44
|
+
generatedAt: new Date().toISOString(),
|
|
45
|
+
problemId: problem.problemId,
|
|
46
|
+
displayName: problem.displayName,
|
|
47
|
+
title: problem.title,
|
|
48
|
+
siteStatus: problem.siteStatus,
|
|
49
|
+
repoStatus: problem.repoStatus,
|
|
50
|
+
archiveMode: 'method_exemplar',
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
writeJson(path.join(archiveDir, 'ARCHIVE.json'), payload);
|
|
54
|
+
writeText(
|
|
55
|
+
path.join(archiveDir, 'ARCHIVE_SUMMARY.md'),
|
|
56
|
+
[
|
|
57
|
+
`# ${problem.displayName} Archive Summary`,
|
|
58
|
+
'',
|
|
59
|
+
`- Title: ${problem.title}`,
|
|
60
|
+
`- Site status: ${problem.siteStatus}`,
|
|
61
|
+
`- Repo status: ${problem.repoStatus}`,
|
|
62
|
+
'',
|
|
63
|
+
'Archive posture:',
|
|
64
|
+
'- treat this solved problem as a method exemplar',
|
|
65
|
+
'- extract reusable arguments, formalization hooks, and references',
|
|
66
|
+
'- do not run the open-problem frontier loop here',
|
|
67
|
+
'',
|
|
68
|
+
].join('\n'),
|
|
69
|
+
);
|
|
70
|
+
writeText(
|
|
71
|
+
path.join(archiveDir, 'METHOD_PACKET.md'),
|
|
72
|
+
[
|
|
73
|
+
`# ${problem.displayName} Method Packet`,
|
|
74
|
+
'',
|
|
75
|
+
'Prompts:',
|
|
76
|
+
'- What method or reduction pattern is reusable?',
|
|
77
|
+
'- What verification surface is already clean here?',
|
|
78
|
+
'- What should be ported into open-problem packs as technique, not as status inflation?',
|
|
79
|
+
'',
|
|
80
|
+
].join('\n'),
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
archiveDir,
|
|
85
|
+
payload,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
@@ -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}
|