erdos-problems 0.1.5 → 0.1.7

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.
@@ -257,22 +257,29 @@ function writeRootProblemBundle(rootDir, problemId, localProblem, upstreamRecord
257
257
  return problemRecord;
258
258
  }
259
259
 
260
- export async function runPullCommand(args) {
260
+ export async function runPullCommand(args, options = {}) {
261
+ const silent = options.silent === true;
261
262
  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]');
263
+ if (!silent) {
264
+ console.log('Usage:');
265
+ console.log(' erdos pull problem <id> [--dest <path>] [--include-site] [--refresh-upstream]');
266
+ console.log(' erdos pull artifacts <id> [--dest <path>] [--refresh-upstream]');
267
+ console.log(' erdos pull literature <id> [--dest <path>] [--include-site] [--refresh-upstream]');
268
+ }
266
269
  return 0;
267
270
  }
268
271
 
269
272
  const parsed = parsePullArgs(args);
270
273
  if (parsed.error) {
271
- console.error(parsed.error);
274
+ if (!silent) {
275
+ console.error(parsed.error);
276
+ }
272
277
  return 1;
273
278
  }
274
279
  if (!parsed.problemId) {
275
- console.error('Missing problem id.');
280
+ if (!silent) {
281
+ console.error('Missing problem id.');
282
+ }
276
283
  return 1;
277
284
  }
278
285
 
@@ -285,7 +292,9 @@ export async function runPullCommand(args) {
285
292
  const upstreamRecord = snapshot?.index?.by_number?.[String(parsed.problemId)] ?? null;
286
293
 
287
294
  if (!localProblem && !upstreamRecord) {
288
- console.error(`Problem ${parsed.problemId} is not present in the local dossier set or upstream snapshot.`);
295
+ if (!silent) {
296
+ console.error(`Problem ${parsed.problemId} is not present in the local dossier set or upstream snapshot.`);
297
+ }
289
298
  return 1;
290
299
  }
291
300
 
@@ -294,10 +303,12 @@ export async function runPullCommand(args) {
294
303
  ? path.resolve(parsed.destination)
295
304
  : getWorkspaceProblemArtifactDir(parsed.problemId);
296
305
  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}`);
306
+ if (!silent) {
307
+ console.log(`Artifact bundle created: ${destination}`);
308
+ console.log(`Local canonical dossier included: ${localProblem ? 'yes' : 'no'}`);
309
+ console.log(`Upstream record included: ${upstreamRecord ? 'yes' : 'no'}`);
310
+ console.log(`Artifacts copied: ${result.copiedArtifacts?.length ?? result.artifactsCopied ?? 0}`);
311
+ }
301
312
  return 0;
302
313
  }
303
314
 
@@ -306,12 +317,14 @@ export async function runPullCommand(args) {
306
317
  ? path.resolve(parsed.destination)
307
318
  : getWorkspaceProblemLiteratureDir(parsed.problemId);
308
319
  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}`);
320
+ if (!silent) {
321
+ console.log(`Literature bundle created: ${destination}`);
322
+ console.log(`Local dossier context included: ${localProblem ? 'yes' : 'no'}`);
323
+ console.log(`Upstream record included: ${upstreamRecord ? 'yes' : 'no'}`);
324
+ console.log(`Live site snapshot included: ${result.siteStatus.included ? 'yes' : 'no'}`);
325
+ if (result.siteStatus.error) {
326
+ console.log(`Live site snapshot note: ${result.siteStatus.error}`);
327
+ }
315
328
  }
316
329
  return 0;
317
330
  }
@@ -341,14 +354,16 @@ export async function runPullCommand(args) {
341
354
  siteSnapshotError: literatureResult.siteStatus.error,
342
355
  });
343
356
 
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}`);
357
+ if (!silent) {
358
+ console.log(`Pull bundle created: ${rootDestination}`);
359
+ console.log(`Artifact lane: ${artifactDestination}`);
360
+ console.log(`Literature lane: ${literatureDestination}`);
361
+ console.log(`Local canonical dossier included: ${localProblem ? 'yes' : 'no'}`);
362
+ console.log(`Upstream record included: ${upstreamRecord ? 'yes' : 'no'}`);
363
+ console.log(`Live site snapshot included: ${literatureResult.siteStatus.included ? 'yes' : 'no'}`);
364
+ if (literatureResult.siteStatus.error) {
365
+ console.log(`Live site snapshot note: ${literatureResult.siteStatus.error}`);
366
+ }
352
367
  }
353
368
  return 0;
354
369
  }
@@ -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
+ }
@@ -0,0 +1,57 @@
1
+ import { getWorkspaceQuestionLedgerPath, getWorkspaceStateMarkdownPath } from '../runtime/paths.js';
2
+ import { loadState, syncState } from '../runtime/state.js';
3
+
4
+ function printState(state) {
5
+ console.log('Erdos research state');
6
+ console.log(`Workspace root: ${state.workspaceRoot}`);
7
+ console.log(`Open problem: ${state.activeProblem || '(none)'}`);
8
+ console.log(`Problem title: ${state.problemTitle || '(none)'}`);
9
+ console.log(`Cluster: ${state.cluster || '(none)'}`);
10
+ console.log(`Family role: ${state.familyRole || '(none)'}`);
11
+ console.log(`Harness profile: ${state.harnessProfile || '(none)'}`);
12
+ console.log(`Active route: ${state.activeRoute || '(none)'}`);
13
+ console.log(`Route breakthrough: ${state.routeBreakthrough ? 'yes' : 'no'}`);
14
+ console.log(`Problem solved: ${state.problemSolved ? 'yes' : 'no'}`);
15
+ console.log(`Continuation mode: ${state.continuation.mode}`);
16
+ console.log(`Current frontier: ${state.currentFrontier.kind} / ${state.currentFrontier.detail}`);
17
+ console.log(`Route story: ${state.routeStory || '(none)'}`);
18
+ console.log(`Checkpoint focus: ${state.checkpointFocus || '(none)'}`);
19
+ console.log(`Next honest move: ${state.nextHonestMove}`);
20
+ console.log(`State markdown: ${getWorkspaceStateMarkdownPath()}`);
21
+ console.log(`Question ledger: ${getWorkspaceQuestionLedgerPath()}`);
22
+ }
23
+
24
+ export function runStateCommand(args) {
25
+ const [subcommand, ...rest] = args;
26
+ const asJson = rest.includes('--json');
27
+
28
+ if (!subcommand || subcommand === 'help' || subcommand === '--help') {
29
+ console.log('Usage:');
30
+ console.log(' erdos state sync [--json]');
31
+ console.log(' erdos state show [--json]');
32
+ return 0;
33
+ }
34
+
35
+ if (subcommand === 'sync') {
36
+ const state = syncState();
37
+ if (asJson) {
38
+ console.log(JSON.stringify(state, null, 2));
39
+ return 0;
40
+ }
41
+ printState(state);
42
+ return 0;
43
+ }
44
+
45
+ if (subcommand === 'show') {
46
+ const state = loadState();
47
+ if (asJson) {
48
+ console.log(JSON.stringify(state, null, 2));
49
+ return 0;
50
+ }
51
+ printState(state);
52
+ return 0;
53
+ }
54
+
55
+ console.error(`Unknown state subcommand: ${subcommand}`);
56
+ return 1;
57
+ }
@@ -35,6 +35,11 @@ function printSunflowerStatus(snapshot, registryPaths) {
35
35
  console.log(`Open problem: ${snapshot.openProblem ? 'yes' : 'no'}`);
36
36
  console.log(`Problem solved: ${snapshot.problemSolved ? 'yes' : 'no'}`);
37
37
  console.log(`Bootstrap focus: ${snapshot.bootstrapFocus ?? '(none)'}`);
38
+ console.log(`Route story: ${snapshot.routeStory ?? '(none)'}`);
39
+ console.log(`Frontier label: ${snapshot.frontierLabel ?? '(none)'}`);
40
+ console.log(`Frontier detail: ${snapshot.frontierDetail ?? '(none)'}`);
41
+ console.log(`Checkpoint focus: ${snapshot.checkpointFocus ?? '(none)'}`);
42
+ console.log(`Next honest move: ${snapshot.nextHonestMove}`);
38
43
  console.log(`Related core problems: ${snapshot.relatedCoreProblems.join(', ') || '(none)'}`);
39
44
  console.log(`Literature focus: ${snapshot.literatureFocus.join(', ') || '(none)'}`);
40
45
  console.log(`Artifact focus: ${snapshot.artifactFocus.join(', ') || '(none)'}`);
@@ -1,4 +1,5 @@
1
1
  import { getProblem } from '../atlas/catalog.js';
2
+ import { loadConfig } from '../runtime/config.js';
2
3
  import { buildSunflowerStatusSnapshot } from '../runtime/sunflower.js';
3
4
  import { getWorkspaceSummary } from '../runtime/workspace.js';
4
5
 
@@ -17,15 +18,33 @@ export function runWorkspaceCommand(args) {
17
18
  }
18
19
 
19
20
  const summary = getWorkspaceSummary();
21
+ const config = loadConfig();
20
22
  console.log(`Workspace root: ${summary.workspaceRoot}`);
21
23
  console.log(`State dir: ${summary.stateDir}`);
22
24
  console.log(`Initialized: ${summary.hasState ? 'yes' : 'no'}`);
23
25
  console.log(`Active problem: ${summary.activeProblem ?? '(none)'}`);
26
+ console.log(`Config path: ${summary.configPath}`);
27
+ console.log(`State file: ${summary.statePath}`);
28
+ console.log(`State markdown: ${summary.stateMarkdownPath}`);
29
+ console.log(`Question ledger: ${summary.questionLedgerPath}`);
30
+ console.log(`Checkpoint shelf: ${summary.checkpointIndexPath}`);
24
31
  console.log(`Workspace upstream dir: ${summary.upstreamDir}`);
32
+ console.log(`Workspace seeded-problems dir: ${summary.seededProblemsDir}`);
25
33
  console.log(`Workspace scaffold dir: ${summary.scaffoldDir}`);
26
34
  console.log(`Workspace pull dir: ${summary.pullDir}`);
27
35
  console.log(`Workspace artifact dir: ${summary.artifactDir}`);
28
36
  console.log(`Workspace literature dir: ${summary.literatureDir}`);
37
+ console.log(`Active seeded dossier dir: ${summary.seededProblemDir}`);
38
+ console.log(`Preferred agent: ${config.preferredAgent}`);
39
+ console.log(`Continuation mode: ${summary.continuationMode ?? config.continuation}`);
40
+ console.log(`Active route: ${summary.activeRoute ?? '(none)'}`);
41
+ console.log(`Route breakthrough: ${summary.routeBreakthrough ? 'yes' : 'no'}`);
42
+ console.log(`Problem solved: ${summary.problemSolved ? 'yes' : 'no'}`);
43
+ console.log(`Checkpoint synced at: ${summary.lastCheckpointSyncAt ?? '(never)'}`);
44
+ console.log(`Next honest move: ${summary.nextHonestMove ?? '(none)'}`);
45
+ if (summary.currentFrontier) {
46
+ console.log(`Current frontier: ${summary.currentFrontier.kind} / ${summary.currentFrontier.detail}`);
47
+ }
29
48
  console.log(`Updated at: ${summary.updatedAt ?? '(none)'}`);
30
49
  if (summary.activeProblem) {
31
50
  const problem = getProblem(summary.activeProblem);
@@ -34,6 +53,7 @@ export function runWorkspaceCommand(args) {
34
53
  console.log(`Sunflower family role: ${sunflower.familyRole ?? '(none)'}`);
35
54
  console.log(`Sunflower harness profile: ${sunflower.harnessProfile ?? '(none)'}`);
36
55
  console.log(`Sunflower route: ${sunflower.activeRoute ?? '(none)'}`);
56
+ console.log(`Sunflower frontier: ${sunflower.frontierDetail ?? '(none)'}`);
37
57
  console.log(`Sunflower compute: ${sunflower.computeLanePresent ? 'yes' : 'no'}`);
38
58
  if (sunflower.activePacket) {
39
59
  console.log(`Sunflower compute lane: ${sunflower.activePacket.laneId} [${sunflower.activePacket.status}]`);