erdos-problems 0.1.4 → 0.1.6
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 +103 -13
- package/docs/ERDOS_PROBLEMS_PROBLEM_SCHEMA.md +65 -60
- package/docs/ERDOS_PROBLEMS_REPO_SPEC.md +97 -214
- package/docs/RESEARCH_LOOP.md +47 -0
- package/package.json +1 -1
- package/packs/sunflower/README.md +6 -4
- package/packs/sunflower/compute/20/u3_uniform_transfer_window_v0.yaml +16 -0
- package/packs/sunflower/problems/20/CONTEXT.md +14 -0
- package/packs/sunflower/problems/20/context.yaml +31 -0
- package/packs/sunflower/problems/536/CONTEXT.md +9 -0
- package/packs/sunflower/problems/536/context.yaml +17 -0
- package/packs/sunflower/problems/856/CONTEXT.md +9 -0
- package/packs/sunflower/problems/856/context.yaml +17 -0
- package/packs/sunflower/problems/857/CONTEXT.md +14 -0
- package/packs/sunflower/problems/857/context.yaml +32 -0
- package/problems/20/problem.yaml +8 -2
- package/problems/536/problem.yaml +9 -3
- package/problems/856/problem.yaml +9 -3
- package/src/cli/index.js +24 -0
- package/src/commands/bootstrap.js +7 -0
- package/src/commands/checkpoints.js +36 -0
- package/src/commands/continuation.js +60 -0
- package/src/commands/maintainer.js +182 -0
- package/src/commands/preflight.js +44 -0
- package/src/commands/problem.js +10 -0
- package/src/commands/pull.js +192 -41
- package/src/commands/state.js +57 -0
- package/src/commands/sunflower.js +12 -0
- package/src/commands/workspace.js +22 -0
- package/src/runtime/checkpoints.js +208 -0
- package/src/runtime/config.js +37 -0
- package/src/runtime/continuation.js +65 -0
- package/src/runtime/git.js +52 -0
- package/src/runtime/maintainer-seed.js +294 -0
- package/src/runtime/paths.js +75 -27
- package/src/runtime/preflight.js +106 -0
- package/src/runtime/problem-artifacts.js +63 -1
- package/src/runtime/state.js +269 -0
- package/src/runtime/sunflower.js +126 -6
- package/src/runtime/workspace.js +42 -22
package/src/commands/pull.js
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { getProblem } from '../atlas/catalog.js';
|
|
3
|
-
import { ensureDir, writeJson, writeText } from '../runtime/files.js';
|
|
4
|
-
import {
|
|
5
|
-
|
|
3
|
+
import { copyFileIfPresent, ensureDir, writeJson, writeText } from '../runtime/files.js';
|
|
4
|
+
import {
|
|
5
|
+
getWorkspaceProblemArtifactDir,
|
|
6
|
+
getWorkspaceProblemLiteratureDir,
|
|
7
|
+
getWorkspaceProblemPullDir,
|
|
8
|
+
} from '../runtime/paths.js';
|
|
9
|
+
import { getProblemArtifactInventory, scaffoldProblem } from '../runtime/problem-artifacts.js';
|
|
6
10
|
import { loadActiveUpstreamSnapshot, syncUpstream } from '../upstream/sync.js';
|
|
7
11
|
import { fetchProblemSiteSnapshot } from '../upstream/site.js';
|
|
8
12
|
|
|
9
13
|
function parsePullArgs(args) {
|
|
10
14
|
const [kind, value, ...rest] = args;
|
|
11
|
-
if (
|
|
12
|
-
return { error: '
|
|
15
|
+
if (!['problem', 'artifacts', 'literature'].includes(kind)) {
|
|
16
|
+
return { error: 'Usage: erdos pull problem|artifacts|literature <id> [--dest <path>] [--include-site] [--refresh-upstream]' };
|
|
13
17
|
}
|
|
14
18
|
|
|
15
19
|
let destination = null;
|
|
@@ -38,6 +42,7 @@ function parsePullArgs(args) {
|
|
|
38
42
|
}
|
|
39
43
|
|
|
40
44
|
return {
|
|
45
|
+
kind,
|
|
41
46
|
problemId: value,
|
|
42
47
|
destination,
|
|
43
48
|
includeSite,
|
|
@@ -45,31 +50,36 @@ function parsePullArgs(args) {
|
|
|
45
50
|
};
|
|
46
51
|
}
|
|
47
52
|
|
|
48
|
-
function
|
|
53
|
+
function buildProblemRecord(problemId, localProblem, upstreamRecord) {
|
|
54
|
+
return {
|
|
55
|
+
generatedAt: new Date().toISOString(),
|
|
56
|
+
problemId: String(problemId),
|
|
57
|
+
title: localProblem?.title ?? `Erdos Problem #${problemId}`,
|
|
58
|
+
cluster: localProblem?.cluster ?? null,
|
|
59
|
+
siteStatus: localProblem?.siteStatus ?? upstreamRecord?.status?.state ?? 'unknown',
|
|
60
|
+
repoStatus: localProblem?.repoStatus ?? 'upstream-only',
|
|
61
|
+
harnessDepth: localProblem?.harnessDepth ?? 'unseeded',
|
|
62
|
+
sourceUrl: localProblem?.sourceUrl ?? `https://www.erdosproblems.com/${problemId}`,
|
|
63
|
+
activeRoute: localProblem?.researchState?.active_route ?? null,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function writeUpstreamOnlyBundle(problemId, destination, upstreamRecord, snapshot, readmeTitle) {
|
|
49
68
|
ensureDir(destination);
|
|
50
69
|
|
|
51
70
|
if (upstreamRecord) {
|
|
52
71
|
writeJson(path.join(destination, 'UPSTREAM_RECORD.json'), upstreamRecord);
|
|
53
72
|
}
|
|
54
73
|
|
|
55
|
-
const
|
|
56
|
-
writeJson(path.join(destination, 'PROBLEM.json'),
|
|
57
|
-
generatedAt,
|
|
58
|
-
problemId,
|
|
59
|
-
title: `Erdos Problem #${problemId}`,
|
|
60
|
-
cluster: null,
|
|
61
|
-
siteStatus: upstreamRecord?.status?.state ?? 'unknown',
|
|
62
|
-
repoStatus: 'upstream-only',
|
|
63
|
-
harnessDepth: 'unseeded',
|
|
64
|
-
sourceUrl: `https://www.erdosproblems.com/${problemId}`,
|
|
65
|
-
activeRoute: null,
|
|
66
|
-
});
|
|
67
|
-
|
|
74
|
+
const problemRecord = buildProblemRecord(problemId, null, upstreamRecord);
|
|
75
|
+
writeJson(path.join(destination, 'PROBLEM.json'), problemRecord);
|
|
68
76
|
writeJson(path.join(destination, 'ARTIFACT_INDEX.json'), {
|
|
69
|
-
generatedAt,
|
|
70
|
-
problemId,
|
|
77
|
+
generatedAt: problemRecord.generatedAt,
|
|
78
|
+
problemId: String(problemId),
|
|
71
79
|
copiedArtifacts: [],
|
|
72
80
|
canonicalArtifacts: [],
|
|
81
|
+
packProblemArtifactsInventory: [],
|
|
82
|
+
computePackets: [],
|
|
73
83
|
upstreamSnapshot: snapshot
|
|
74
84
|
? {
|
|
75
85
|
kind: snapshot.kind,
|
|
@@ -82,11 +92,10 @@ function writeUpstreamOnlyBundle(problemId, destination, upstreamRecord, snapsho
|
|
|
82
92
|
: null,
|
|
83
93
|
includedUpstreamRecord: Boolean(upstreamRecord),
|
|
84
94
|
});
|
|
85
|
-
|
|
86
95
|
writeText(
|
|
87
96
|
path.join(destination, 'README.md'),
|
|
88
97
|
[
|
|
89
|
-
`#
|
|
98
|
+
`# ${readmeTitle}`,
|
|
90
99
|
'',
|
|
91
100
|
'This bundle was generated from upstream public metadata.',
|
|
92
101
|
'',
|
|
@@ -97,6 +106,20 @@ function writeUpstreamOnlyBundle(problemId, destination, upstreamRecord, snapsho
|
|
|
97
106
|
'',
|
|
98
107
|
].join('\n'),
|
|
99
108
|
);
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
problemRecord,
|
|
112
|
+
artifactsCopied: 0,
|
|
113
|
+
inventory: null,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function writeArtifactsLane(problemId, destination, localProblem, upstreamRecord, snapshot) {
|
|
118
|
+
if (localProblem) {
|
|
119
|
+
return scaffoldProblem(localProblem, destination);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return writeUpstreamOnlyBundle(problemId, destination, upstreamRecord, snapshot, `Erdos Problem ${problemId} Artifact Bundle`);
|
|
100
123
|
}
|
|
101
124
|
|
|
102
125
|
async function maybeWriteSiteBundle(problemId, destination, includeSite) {
|
|
@@ -136,10 +159,110 @@ async function maybeWriteSiteBundle(problemId, destination, includeSite) {
|
|
|
136
159
|
}
|
|
137
160
|
}
|
|
138
161
|
|
|
162
|
+
async function writeLiteratureLane(problemId, destination, localProblem, upstreamRecord, includeSite) {
|
|
163
|
+
ensureDir(destination);
|
|
164
|
+
|
|
165
|
+
const includedFiles = [];
|
|
166
|
+
const copied = (sourcePath, destinationName, label) => {
|
|
167
|
+
const destinationPath = path.join(destination, destinationName);
|
|
168
|
+
if (copyFileIfPresent(sourcePath, destinationPath)) {
|
|
169
|
+
includedFiles.push({ label, sourcePath, destinationPath });
|
|
170
|
+
return true;
|
|
171
|
+
}
|
|
172
|
+
return false;
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
if (upstreamRecord) {
|
|
176
|
+
writeJson(path.join(destination, 'UPSTREAM_RECORD.json'), upstreamRecord);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
let inventory = null;
|
|
180
|
+
if (localProblem) {
|
|
181
|
+
inventory = getProblemArtifactInventory(localProblem);
|
|
182
|
+
copied(localProblem.referencesPath, 'REFERENCES.md', 'REFERENCES.md');
|
|
183
|
+
copied(localProblem.statementPath, 'STATEMENT.md', 'STATEMENT.md');
|
|
184
|
+
if (inventory.packContext?.exists) {
|
|
185
|
+
copied(inventory.packContext.path, 'PACK_CONTEXT.md', inventory.packContext.label);
|
|
186
|
+
}
|
|
187
|
+
for (const artifact of inventory.packProblemArtifacts) {
|
|
188
|
+
copied(artifact.path, path.join('PACK_PROBLEM', artifact.destinationName), artifact.label);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const siteStatus = await maybeWriteSiteBundle(problemId, destination, includeSite);
|
|
193
|
+
const problemRecord = buildProblemRecord(problemId, localProblem, upstreamRecord);
|
|
194
|
+
writeJson(path.join(destination, 'PROBLEM.json'), problemRecord);
|
|
195
|
+
writeJson(path.join(destination, 'LITERATURE_INDEX.json'), {
|
|
196
|
+
generatedAt: new Date().toISOString(),
|
|
197
|
+
problemId: String(problemId),
|
|
198
|
+
includedFiles,
|
|
199
|
+
includedUpstreamRecord: Boolean(upstreamRecord),
|
|
200
|
+
includedSiteSnapshot: siteStatus.included,
|
|
201
|
+
siteSnapshotError: siteStatus.error,
|
|
202
|
+
});
|
|
203
|
+
writeText(
|
|
204
|
+
path.join(destination, 'README.md'),
|
|
205
|
+
[
|
|
206
|
+
`# Erdos Problem ${problemId} Literature Bundle`,
|
|
207
|
+
'',
|
|
208
|
+
'This literature lane was generated by the erdos CLI.',
|
|
209
|
+
'',
|
|
210
|
+
`- Local dossier included: ${localProblem ? 'yes' : 'no'}`,
|
|
211
|
+
`- Upstream record included: ${upstreamRecord ? 'yes' : 'no'}`,
|
|
212
|
+
`- Live site snapshot included: ${siteStatus.included ? 'yes' : 'no'}`,
|
|
213
|
+
'',
|
|
214
|
+
].join('\n'),
|
|
215
|
+
);
|
|
216
|
+
|
|
217
|
+
return {
|
|
218
|
+
destination,
|
|
219
|
+
includedFiles,
|
|
220
|
+
siteStatus,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function writeRootProblemBundle(rootDir, problemId, localProblem, upstreamRecord, snapshot, artifactsDir, literatureDir) {
|
|
225
|
+
ensureDir(rootDir);
|
|
226
|
+
const problemRecord = buildProblemRecord(problemId, localProblem, upstreamRecord);
|
|
227
|
+
|
|
228
|
+
if (upstreamRecord) {
|
|
229
|
+
writeJson(path.join(rootDir, 'UPSTREAM_RECORD.json'), upstreamRecord);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
writeJson(path.join(rootDir, 'PROBLEM.json'), problemRecord);
|
|
233
|
+
writeJson(path.join(rootDir, 'PULL_INDEX.json'), {
|
|
234
|
+
generatedAt: new Date().toISOString(),
|
|
235
|
+
problemId: String(problemId),
|
|
236
|
+
rootDir,
|
|
237
|
+
artifactsDir,
|
|
238
|
+
literatureDir,
|
|
239
|
+
snapshotKind: snapshot?.kind ?? null,
|
|
240
|
+
upstreamCommit: snapshot?.manifest.upstream_commit ?? null,
|
|
241
|
+
});
|
|
242
|
+
writeText(
|
|
243
|
+
path.join(rootDir, 'README.md'),
|
|
244
|
+
[
|
|
245
|
+
`# Erdos Problem ${problemId} Pull Bundle`,
|
|
246
|
+
'',
|
|
247
|
+
'This pull bundle contains per-problem workspace lanes for artifacts and literature.',
|
|
248
|
+
'',
|
|
249
|
+
`- Artifacts lane: ${artifactsDir}`,
|
|
250
|
+
`- Literature lane: ${literatureDir}`,
|
|
251
|
+
`- Local canonical dossier available: ${localProblem ? 'yes' : 'no'}`,
|
|
252
|
+
`- Upstream record included: ${upstreamRecord ? 'yes' : 'no'}`,
|
|
253
|
+
'',
|
|
254
|
+
].join('\n'),
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
return problemRecord;
|
|
258
|
+
}
|
|
259
|
+
|
|
139
260
|
export async function runPullCommand(args) {
|
|
140
261
|
if (args.length === 0 || args[0] === 'help' || args[0] === '--help') {
|
|
141
262
|
console.log('Usage:');
|
|
142
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]');
|
|
143
266
|
return 0;
|
|
144
267
|
}
|
|
145
268
|
|
|
@@ -166,38 +289,66 @@ export async function runPullCommand(args) {
|
|
|
166
289
|
return 1;
|
|
167
290
|
}
|
|
168
291
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
292
|
+
if (parsed.kind === 'artifacts') {
|
|
293
|
+
const destination = parsed.destination
|
|
294
|
+
? path.resolve(parsed.destination)
|
|
295
|
+
: getWorkspaceProblemArtifactDir(parsed.problemId);
|
|
296
|
+
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}`);
|
|
301
|
+
return 0;
|
|
302
|
+
}
|
|
172
303
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
304
|
+
if (parsed.kind === 'literature') {
|
|
305
|
+
const destination = parsed.destination
|
|
306
|
+
? path.resolve(parsed.destination)
|
|
307
|
+
: getWorkspaceProblemLiteratureDir(parsed.problemId);
|
|
308
|
+
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}`);
|
|
315
|
+
}
|
|
316
|
+
return 0;
|
|
178
317
|
}
|
|
179
318
|
|
|
319
|
+
const rootDestination = parsed.destination
|
|
320
|
+
? path.resolve(parsed.destination)
|
|
321
|
+
: getWorkspaceProblemPullDir(parsed.problemId);
|
|
322
|
+
const artifactDestination = path.join(rootDestination, 'artifacts');
|
|
323
|
+
const literatureDestination = path.join(rootDestination, 'literature');
|
|
180
324
|
|
|
181
|
-
|
|
325
|
+
writeRootProblemBundle(rootDestination, String(parsed.problemId), localProblem, upstreamRecord, snapshot, artifactDestination, literatureDestination);
|
|
326
|
+
const artifactResult = writeArtifactsLane(String(parsed.problemId), artifactDestination, localProblem, upstreamRecord, snapshot);
|
|
327
|
+
const literatureResult = await writeLiteratureLane(String(parsed.problemId), literatureDestination, localProblem, upstreamRecord, parsed.includeSite);
|
|
182
328
|
|
|
183
|
-
writeJson(path.join(
|
|
329
|
+
writeJson(path.join(rootDestination, 'PULL_STATUS.json'), {
|
|
184
330
|
generatedAt: new Date().toISOString(),
|
|
185
331
|
problemId: String(parsed.problemId),
|
|
186
332
|
usedLocalDossier: Boolean(localProblem),
|
|
187
333
|
includedUpstreamRecord: Boolean(upstreamRecord),
|
|
188
334
|
upstreamSnapshotKind: snapshot?.kind ?? null,
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
335
|
+
artifactLanePath: artifactDestination,
|
|
336
|
+
literatureLanePath: literatureDestination,
|
|
337
|
+
artifactArtifactsCopied: artifactResult.copiedArtifacts?.length ?? artifactResult.artifactsCopied ?? 0,
|
|
338
|
+
literatureFilesCopied: literatureResult.includedFiles.length,
|
|
339
|
+
siteSnapshotAttempted: literatureResult.siteStatus.attempted,
|
|
340
|
+
siteSnapshotIncluded: literatureResult.siteStatus.included,
|
|
341
|
+
siteSnapshotError: literatureResult.siteStatus.error,
|
|
193
342
|
});
|
|
194
343
|
|
|
195
|
-
console.log(`Pull bundle created: ${
|
|
344
|
+
console.log(`Pull bundle created: ${rootDestination}`);
|
|
345
|
+
console.log(`Artifact lane: ${artifactDestination}`);
|
|
346
|
+
console.log(`Literature lane: ${literatureDestination}`);
|
|
196
347
|
console.log(`Local canonical dossier included: ${localProblem ? 'yes' : 'no'}`);
|
|
197
348
|
console.log(`Upstream record included: ${upstreamRecord ? 'yes' : 'no'}`);
|
|
198
|
-
console.log(`Live site snapshot included: ${siteStatus.included ? 'yes' : 'no'}`);
|
|
199
|
-
if (siteStatus.error) {
|
|
200
|
-
console.log(`Live site snapshot note: ${siteStatus.error}`);
|
|
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}`);
|
|
201
352
|
}
|
|
202
353
|
return 0;
|
|
203
354
|
}
|
|
@@ -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
|
+
}
|
|
@@ -28,10 +28,22 @@ function parseStatusArgs(args) {
|
|
|
28
28
|
function printSunflowerStatus(snapshot, registryPaths) {
|
|
29
29
|
console.log(`${snapshot.displayName} sunflower harness`);
|
|
30
30
|
console.log(`Title: ${snapshot.title}`);
|
|
31
|
+
console.log(`Family role: ${snapshot.familyRole ?? '(none)'}`);
|
|
32
|
+
console.log(`Harness profile: ${snapshot.harnessProfile ?? '(none)'}`);
|
|
31
33
|
console.log(`Active route: ${snapshot.activeRoute ?? '(none)'}`);
|
|
32
34
|
console.log(`Route breakthrough: ${snapshot.routeBreakthrough ? 'yes' : 'no'}`);
|
|
33
35
|
console.log(`Open problem: ${snapshot.openProblem ? 'yes' : 'no'}`);
|
|
34
36
|
console.log(`Problem solved: ${snapshot.problemSolved ? 'yes' : 'no'}`);
|
|
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}`);
|
|
43
|
+
console.log(`Related core problems: ${snapshot.relatedCoreProblems.join(', ') || '(none)'}`);
|
|
44
|
+
console.log(`Literature focus: ${snapshot.literatureFocus.join(', ') || '(none)'}`);
|
|
45
|
+
console.log(`Artifact focus: ${snapshot.artifactFocus.join(', ') || '(none)'}`);
|
|
46
|
+
console.log(`Context file: ${snapshot.contextPath ?? '(none)'}`);
|
|
35
47
|
console.log(`Compute lane present: ${snapshot.computeLanePresent ? 'yes' : 'no'}`);
|
|
36
48
|
console.log(`Compute lane count: ${snapshot.computeLaneCount}`);
|
|
37
49
|
console.log(`Compute summary: ${snapshot.computeSummary}`);
|
|
@@ -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,19 +18,40 @@ 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}`);
|
|
25
32
|
console.log(`Workspace scaffold dir: ${summary.scaffoldDir}`);
|
|
26
33
|
console.log(`Workspace pull dir: ${summary.pullDir}`);
|
|
34
|
+
console.log(`Workspace artifact dir: ${summary.artifactDir}`);
|
|
35
|
+
console.log(`Workspace literature dir: ${summary.literatureDir}`);
|
|
36
|
+
console.log(`Preferred agent: ${config.preferredAgent}`);
|
|
37
|
+
console.log(`Continuation mode: ${summary.continuationMode ?? config.continuation}`);
|
|
38
|
+
console.log(`Active route: ${summary.activeRoute ?? '(none)'}`);
|
|
39
|
+
console.log(`Route breakthrough: ${summary.routeBreakthrough ? 'yes' : 'no'}`);
|
|
40
|
+
console.log(`Problem solved: ${summary.problemSolved ? 'yes' : 'no'}`);
|
|
41
|
+
console.log(`Checkpoint synced at: ${summary.lastCheckpointSyncAt ?? '(never)'}`);
|
|
42
|
+
console.log(`Next honest move: ${summary.nextHonestMove ?? '(none)'}`);
|
|
43
|
+
if (summary.currentFrontier) {
|
|
44
|
+
console.log(`Current frontier: ${summary.currentFrontier.kind} / ${summary.currentFrontier.detail}`);
|
|
45
|
+
}
|
|
27
46
|
console.log(`Updated at: ${summary.updatedAt ?? '(none)'}`);
|
|
28
47
|
if (summary.activeProblem) {
|
|
29
48
|
const problem = getProblem(summary.activeProblem);
|
|
30
49
|
if (problem?.cluster === 'sunflower') {
|
|
31
50
|
const sunflower = buildSunflowerStatusSnapshot(problem);
|
|
51
|
+
console.log(`Sunflower family role: ${sunflower.familyRole ?? '(none)'}`);
|
|
52
|
+
console.log(`Sunflower harness profile: ${sunflower.harnessProfile ?? '(none)'}`);
|
|
32
53
|
console.log(`Sunflower route: ${sunflower.activeRoute ?? '(none)'}`);
|
|
54
|
+
console.log(`Sunflower frontier: ${sunflower.frontierDetail ?? '(none)'}`);
|
|
33
55
|
console.log(`Sunflower compute: ${sunflower.computeLanePresent ? 'yes' : 'no'}`);
|
|
34
56
|
if (sunflower.activePacket) {
|
|
35
57
|
console.log(`Sunflower compute lane: ${sunflower.activePacket.laneId} [${sunflower.activePacket.status}]`);
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { loadLocalProblems, getProblem } from '../atlas/catalog.js';
|
|
3
|
+
import { loadConfig } from './config.js';
|
|
4
|
+
import { ensureDir, writeJson, writeText } from './files.js';
|
|
5
|
+
import {
|
|
6
|
+
getWorkspaceCheckpointIndexPath,
|
|
7
|
+
getWorkspaceCheckpointJsonPath,
|
|
8
|
+
getWorkspaceCheckpointsDir,
|
|
9
|
+
getWorkspaceProblemCheckpointsDir,
|
|
10
|
+
getWorkspaceRoot,
|
|
11
|
+
getWorkspaceRouteCheckpointsDir,
|
|
12
|
+
} from './paths.js';
|
|
13
|
+
import { getProblemArtifactInventory } from './problem-artifacts.js';
|
|
14
|
+
import { buildSunflowerStatusSnapshot } from './sunflower.js';
|
|
15
|
+
import { loadState, saveState, syncState } from './state.js';
|
|
16
|
+
|
|
17
|
+
function safeName(value) {
|
|
18
|
+
return String(value).replace(/[^a-zA-Z0-9_-]+/g, '-');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function renderCanonicalArtifacts(inventory) {
|
|
22
|
+
return inventory.canonicalArtifacts
|
|
23
|
+
.map((artifact) => `- ${artifact.label}: ${artifact.exists ? 'present' : 'missing'} (${artifact.path})`)
|
|
24
|
+
.join('\n');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function renderProblemCheckpoint(problem, state) {
|
|
28
|
+
const inventory = getProblemArtifactInventory(problem);
|
|
29
|
+
const sunflower = problem.cluster === 'sunflower' ? buildSunflowerStatusSnapshot(problem) : null;
|
|
30
|
+
const research = problem.researchState ?? {};
|
|
31
|
+
const activeRoute = sunflower?.activeRoute ?? research.active_route ?? '(none)';
|
|
32
|
+
const routeBreakthrough = sunflower?.routeBreakthrough ?? Boolean(research.route_breakthrough);
|
|
33
|
+
const problemSolved = sunflower?.problemSolved ?? Boolean(research.problem_solved);
|
|
34
|
+
const nextHonestMove = sunflower?.nextHonestMove
|
|
35
|
+
?? (activeRoute !== '(none)' ? `Advance ${activeRoute} against the dossier and evidence bundle.` : 'Seed or choose an active route.');
|
|
36
|
+
const frontier = sunflower?.frontierDetail ?? problem.shortStatement;
|
|
37
|
+
const checkpointFocus = sunflower?.checkpointFocus ?? 'Keep local route claims and upstream public status cleanly separated.';
|
|
38
|
+
|
|
39
|
+
return `# Problem ${problem.problemId} Checkpoint
|
|
40
|
+
|
|
41
|
+
## Status Ladder
|
|
42
|
+
|
|
43
|
+
- Open Problem: ${problem.problemId}
|
|
44
|
+
- Active Route: ${activeRoute}
|
|
45
|
+
- Route Breakthrough: ${routeBreakthrough ? 'yes' : 'no'}
|
|
46
|
+
- Problem Solved: ${problemSolved ? 'yes' : 'no'}
|
|
47
|
+
|
|
48
|
+
## Problem Record
|
|
49
|
+
|
|
50
|
+
- Title: ${problem.title}
|
|
51
|
+
- Cluster: ${problem.cluster}
|
|
52
|
+
- Source: ${problem.sourceUrl}
|
|
53
|
+
- Site status: ${problem.siteStatus}
|
|
54
|
+
- Repo status: ${problem.repoStatus}
|
|
55
|
+
- Harness depth: ${problem.harnessDepth}
|
|
56
|
+
|
|
57
|
+
## Current Frontier
|
|
58
|
+
|
|
59
|
+
- ${frontier}
|
|
60
|
+
|
|
61
|
+
## Checkpoint Focus
|
|
62
|
+
|
|
63
|
+
- ${checkpointFocus}
|
|
64
|
+
|
|
65
|
+
## Next Honest Move
|
|
66
|
+
|
|
67
|
+
- ${nextHonestMove}
|
|
68
|
+
|
|
69
|
+
## Canonical Artifacts
|
|
70
|
+
|
|
71
|
+
${renderCanonicalArtifacts(inventory)}
|
|
72
|
+
|
|
73
|
+
## Continuation Frame
|
|
74
|
+
|
|
75
|
+
- Active agent: ${state.activeAgent || '(none)'}
|
|
76
|
+
- Continuation mode: ${state.continuation.mode}
|
|
77
|
+
- Stop rule: ${state.continuation.stopRule}
|
|
78
|
+
`;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function renderRouteCheckpoint(problem, state) {
|
|
82
|
+
const sunflower = problem.cluster === 'sunflower' ? buildSunflowerStatusSnapshot(problem) : null;
|
|
83
|
+
const frontier = sunflower?.frontierDetail ?? state.currentFrontier.detail;
|
|
84
|
+
const routeStory = sunflower?.routeStory ?? state.routeStory ?? '(none yet)';
|
|
85
|
+
const checkpointFocus = sunflower?.checkpointFocus ?? state.checkpointFocus ?? '(none yet)';
|
|
86
|
+
|
|
87
|
+
return `# Problem ${problem.problemId} Active Route Checkpoint
|
|
88
|
+
|
|
89
|
+
## Status Ladder
|
|
90
|
+
|
|
91
|
+
- Open Problem: ${problem.problemId}
|
|
92
|
+
- Active Route: ${state.activeRoute || '(none)'}
|
|
93
|
+
- Route Breakthrough: ${state.routeBreakthrough ? 'yes' : 'no'}
|
|
94
|
+
- Problem Solved: ${state.problemSolved ? 'yes' : 'no'}
|
|
95
|
+
|
|
96
|
+
## Current Frontier
|
|
97
|
+
|
|
98
|
+
- ${frontier}
|
|
99
|
+
|
|
100
|
+
## Route Story
|
|
101
|
+
|
|
102
|
+
- ${routeStory}
|
|
103
|
+
|
|
104
|
+
## Checkpoint Focus
|
|
105
|
+
|
|
106
|
+
- ${checkpointFocus}
|
|
107
|
+
|
|
108
|
+
## Continuation Frame
|
|
109
|
+
|
|
110
|
+
- Continuation mode: ${state.continuation.mode}
|
|
111
|
+
- Stop rule: ${state.continuation.stopRule}
|
|
112
|
+
- Next honest move: ${state.nextHonestMove}
|
|
113
|
+
`;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function renderIndex(state, checkpoints) {
|
|
117
|
+
const problemRows = checkpoints.filter((entry) => entry.kind === 'problem');
|
|
118
|
+
const routeRows = checkpoints.filter((entry) => entry.kind === 'route');
|
|
119
|
+
|
|
120
|
+
return [
|
|
121
|
+
'# Erdos Checkpoints',
|
|
122
|
+
'',
|
|
123
|
+
'This is the human-facing checkpoint shelf for the local research-loop runtime.',
|
|
124
|
+
'Canonical truth still lives in dossiers, pack artifacts, upstream snapshots, and generated workspace bundles.',
|
|
125
|
+
'',
|
|
126
|
+
'## Current Status Ladder',
|
|
127
|
+
'',
|
|
128
|
+
`- Open Problem: ${state.activeProblem || '(none)'}`,
|
|
129
|
+
`- Active Route: ${state.activeRoute || '(none)'}`,
|
|
130
|
+
`- Route Breakthrough: ${state.routeBreakthrough ? 'yes' : 'no'}`,
|
|
131
|
+
`- Problem Solved: ${state.problemSolved ? 'yes' : 'no'}`,
|
|
132
|
+
'',
|
|
133
|
+
'## Working Context',
|
|
134
|
+
'',
|
|
135
|
+
`- Continuation Mode: ${state.continuation.mode}`,
|
|
136
|
+
`- Next Honest Move: ${state.nextHonestMove}`,
|
|
137
|
+
'',
|
|
138
|
+
'## Problem Checkpoints',
|
|
139
|
+
'',
|
|
140
|
+
...(problemRows.length > 0 ? problemRows.map((row) => `- [${row.label}](${row.relativePath})`) : ['- *(none)*']),
|
|
141
|
+
'',
|
|
142
|
+
'## Route Checkpoints',
|
|
143
|
+
'',
|
|
144
|
+
...(routeRows.length > 0 ? routeRows.map((row) => `- [${row.label}](${row.relativePath})`) : ['- *(none)*']),
|
|
145
|
+
'',
|
|
146
|
+
].join('\n');
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function syncCheckpoints(workspaceRoot = getWorkspaceRoot()) {
|
|
150
|
+
const config = loadConfig(workspaceRoot);
|
|
151
|
+
const state = syncState(workspaceRoot);
|
|
152
|
+
const problems = loadLocalProblems();
|
|
153
|
+
|
|
154
|
+
ensureDir(getWorkspaceCheckpointsDir(workspaceRoot));
|
|
155
|
+
ensureDir(getWorkspaceProblemCheckpointsDir(workspaceRoot));
|
|
156
|
+
ensureDir(getWorkspaceRouteCheckpointsDir(workspaceRoot));
|
|
157
|
+
|
|
158
|
+
const checkpoints = [];
|
|
159
|
+
|
|
160
|
+
for (const problem of problems) {
|
|
161
|
+
const filename = `problem-${problem.problemId}.md`;
|
|
162
|
+
const fullPath = path.join(getWorkspaceProblemCheckpointsDir(workspaceRoot), filename);
|
|
163
|
+
writeText(fullPath, renderProblemCheckpoint(problem, state));
|
|
164
|
+
checkpoints.push({
|
|
165
|
+
kind: 'problem',
|
|
166
|
+
label: `Problem ${problem.problemId}`,
|
|
167
|
+
path: fullPath,
|
|
168
|
+
relativePath: path.relative(getWorkspaceCheckpointsDir(workspaceRoot), fullPath),
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (state.activeProblem && state.activeRoute) {
|
|
173
|
+
const problem = getProblem(state.activeProblem);
|
|
174
|
+
if (problem) {
|
|
175
|
+
const filename = `problem-${state.activeProblem}--${safeName(state.activeRoute)}.md`;
|
|
176
|
+
const fullPath = path.join(getWorkspaceRouteCheckpointsDir(workspaceRoot), filename);
|
|
177
|
+
writeText(fullPath, renderRouteCheckpoint(problem, state));
|
|
178
|
+
checkpoints.push({
|
|
179
|
+
kind: 'route',
|
|
180
|
+
label: `Problem ${state.activeProblem} / ${state.activeRoute}`,
|
|
181
|
+
path: fullPath,
|
|
182
|
+
relativePath: path.relative(getWorkspaceCheckpointsDir(workspaceRoot), fullPath),
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
writeText(getWorkspaceCheckpointIndexPath(workspaceRoot), renderIndex(state, checkpoints));
|
|
188
|
+
writeJson(getWorkspaceCheckpointJsonPath(workspaceRoot), {
|
|
189
|
+
syncedAt: new Date().toISOString(),
|
|
190
|
+
activeProblem: state.activeProblem,
|
|
191
|
+
activeRoute: state.activeRoute,
|
|
192
|
+
continuationMode: state.continuation.mode,
|
|
193
|
+
activeAgent: config.preferredAgent,
|
|
194
|
+
checkpoints,
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
const nextState = saveState({
|
|
198
|
+
...loadState(workspaceRoot),
|
|
199
|
+
lastCheckpointSyncAt: new Date().toISOString(),
|
|
200
|
+
}, workspaceRoot);
|
|
201
|
+
|
|
202
|
+
return {
|
|
203
|
+
indexPath: getWorkspaceCheckpointIndexPath(workspaceRoot),
|
|
204
|
+
checkpointJsonPath: getWorkspaceCheckpointJsonPath(workspaceRoot),
|
|
205
|
+
checkpoints,
|
|
206
|
+
state: nextState,
|
|
207
|
+
};
|
|
208
|
+
}
|