erdos-problems 0.1.0 → 0.1.2
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 +73 -3
- package/data/upstream/erdosproblems/PROBLEMS_INDEX.json +44420 -0
- package/data/upstream/erdosproblems/SYNC_MANIFEST.json +9 -0
- package/data/upstream/erdosproblems/problems.yaml +13077 -0
- package/docs/ERDOS_PROBLEMS_PROBLEM_SCHEMA.md +104 -119
- package/package.json +5 -1
- package/problems/1008/EVIDENCE.md +4 -0
- package/problems/1008/FORMALIZATION.md +5 -0
- package/problems/1008/REFERENCES.md +5 -0
- package/problems/1008/STATEMENT.md +9 -0
- package/problems/1008/problem.yaml +37 -0
- package/problems/18/EVIDENCE.md +4 -0
- package/problems/18/FORMALIZATION.md +5 -0
- package/problems/18/REFERENCES.md +6 -0
- package/problems/18/STATEMENT.md +12 -0
- package/problems/18/problem.yaml +38 -0
- package/problems/20/problem.yaml +30 -8
- package/problems/536/problem.yaml +30 -8
- package/problems/542/EVIDENCE.md +6 -0
- package/problems/542/FORMALIZATION.md +5 -0
- package/problems/542/REFERENCES.md +5 -0
- package/problems/542/STATEMENT.md +11 -0
- package/problems/542/problem.yaml +38 -0
- package/problems/856/problem.yaml +30 -8
- package/problems/857/problem.yaml +31 -9
- package/problems/89/EVIDENCE.md +4 -0
- package/problems/89/FORMALIZATION.md +5 -0
- package/problems/89/REFERENCES.md +6 -0
- package/problems/89/STATEMENT.md +10 -0
- package/problems/89/problem.yaml +37 -0
- package/src/atlas/catalog.js +83 -72
- package/src/cli/index.js +16 -1
- package/src/commands/bootstrap.js +81 -0
- package/src/commands/dossier.js +19 -11
- package/src/commands/problem.js +117 -8
- package/src/commands/scaffold.js +60 -0
- package/src/commands/upstream.js +60 -0
- package/src/commands/workspace.js +2 -0
- package/src/runtime/files.js +37 -0
- package/src/runtime/paths.js +64 -0
- package/src/runtime/problem-artifacts.js +150 -0
- package/src/runtime/workspace.js +7 -7
- package/src/upstream/sync.js +272 -0
|
@@ -1,23 +1,45 @@
|
|
|
1
1
|
problem_id: "857"
|
|
2
2
|
display_name: "Erdos Problem #857"
|
|
3
|
-
title:
|
|
3
|
+
title: Sunflower Conjecture
|
|
4
4
|
source:
|
|
5
|
-
site:
|
|
6
|
-
url:
|
|
5
|
+
site: erdosproblems.com
|
|
6
|
+
url: https://www.erdosproblems.com/857
|
|
7
7
|
external_id: "857"
|
|
8
|
+
upstream:
|
|
9
|
+
repo: https://github.com/teorth/erdosproblems
|
|
10
|
+
data_file: data/problems.yaml
|
|
11
|
+
number: "857"
|
|
8
12
|
status:
|
|
9
|
-
site_status:
|
|
10
|
-
|
|
11
|
-
|
|
13
|
+
site_status: open
|
|
14
|
+
site_badge: OPEN
|
|
15
|
+
repo_status: active
|
|
16
|
+
upstream_status: open
|
|
17
|
+
upstream_last_update: 2025-08-31
|
|
18
|
+
cluster: sunflower
|
|
19
|
+
prize:
|
|
20
|
+
display: no
|
|
12
21
|
related_problems:
|
|
13
22
|
- "20"
|
|
14
23
|
- "536"
|
|
15
24
|
- "856"
|
|
16
25
|
family_tags:
|
|
17
|
-
-
|
|
18
|
-
-
|
|
26
|
+
- sunflower
|
|
27
|
+
- extremal-set-theory
|
|
28
|
+
harness:
|
|
29
|
+
depth: deep
|
|
30
|
+
statement:
|
|
31
|
+
short: Bound the weak sunflower number m(n,k) by C(k)^n and sharpen the current
|
|
32
|
+
active route toward asymptotic closure.
|
|
33
|
+
normalized_md_path: STATEMENT.md
|
|
34
|
+
references_path: REFERENCES.md
|
|
35
|
+
evidence_path: EVIDENCE.md
|
|
36
|
+
formalization_path: FORMALIZATION.md
|
|
37
|
+
formalization:
|
|
38
|
+
status: active
|
|
39
|
+
upstream_state: no
|
|
40
|
+
upstream_last_update: 2025-08-31
|
|
19
41
|
research_state:
|
|
20
42
|
open_problem: true
|
|
21
|
-
active_route:
|
|
43
|
+
active_route: anchored_selector_linearization
|
|
22
44
|
route_breakthrough: true
|
|
23
45
|
problem_solved: false
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Problem 89 Statement
|
|
2
|
+
|
|
3
|
+
Source: <https://www.erdosproblems.com/89>
|
|
4
|
+
|
|
5
|
+
Normalized focus:
|
|
6
|
+
- distinct distances in the plane
|
|
7
|
+
- near-optimal lower bounds
|
|
8
|
+
|
|
9
|
+
Core question:
|
|
10
|
+
- Does every set of `n` distinct points in `R^2` determine at least a constant multiple of `n / sqrt(log n)` distinct distances?
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
problem_id: "89"
|
|
2
|
+
display_name: "Erdos Problem #89"
|
|
3
|
+
title: Distinct Distances Lower Bound
|
|
4
|
+
source:
|
|
5
|
+
site: erdosproblems.com
|
|
6
|
+
url: https://www.erdosproblems.com/89
|
|
7
|
+
external_id: "89"
|
|
8
|
+
upstream:
|
|
9
|
+
repo: https://github.com/teorth/erdosproblems
|
|
10
|
+
data_file: data/problems.yaml
|
|
11
|
+
number: "89"
|
|
12
|
+
status:
|
|
13
|
+
site_status: open
|
|
14
|
+
site_badge: OPEN
|
|
15
|
+
repo_status: cataloged
|
|
16
|
+
upstream_status: open
|
|
17
|
+
upstream_last_update: 2025-08-31
|
|
18
|
+
cluster: geometry
|
|
19
|
+
prize:
|
|
20
|
+
display: $500
|
|
21
|
+
related_problems: []
|
|
22
|
+
family_tags:
|
|
23
|
+
- geometry
|
|
24
|
+
- distances
|
|
25
|
+
harness:
|
|
26
|
+
depth: dossier
|
|
27
|
+
statement:
|
|
28
|
+
short: Ask whether every n-point set in the plane determines at least a constant
|
|
29
|
+
multiple of n/sqrt(log n) distinct distances.
|
|
30
|
+
normalized_md_path: STATEMENT.md
|
|
31
|
+
references_path: REFERENCES.md
|
|
32
|
+
evidence_path: EVIDENCE.md
|
|
33
|
+
formalization_path: FORMALIZATION.md
|
|
34
|
+
formalization:
|
|
35
|
+
status: statement-formalized
|
|
36
|
+
upstream_state: yes
|
|
37
|
+
upstream_last_update: 2025-10-24
|
package/src/atlas/catalog.js
CHANGED
|
@@ -1,81 +1,88 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { parse } from 'yaml';
|
|
4
|
+
import { getProblemDir, repoRoot } from '../runtime/paths.js';
|
|
5
|
+
|
|
6
|
+
let cachedProblems = null;
|
|
7
|
+
|
|
8
|
+
function readProblemRecord(problemId) {
|
|
9
|
+
const problemDir = getProblemDir(problemId);
|
|
10
|
+
const yamlPath = path.join(problemDir, 'problem.yaml');
|
|
11
|
+
const record = parse(fs.readFileSync(yamlPath, 'utf8'));
|
|
12
|
+
return { problemDir, record };
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function toCatalogProblem(problemDir, record) {
|
|
16
|
+
const statementRelative = record.statement?.normalized_md_path ?? 'STATEMENT.md';
|
|
17
|
+
const referencesRelative = record.references_path ?? 'REFERENCES.md';
|
|
18
|
+
const evidenceRelative = record.evidence_path ?? 'EVIDENCE.md';
|
|
19
|
+
const formalizationRelative = record.formalization_path ?? 'FORMALIZATION.md';
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
problemId: String(record.problem_id),
|
|
23
|
+
displayName: record.display_name,
|
|
24
|
+
title: record.title,
|
|
25
|
+
sourceUrl: record.source?.url,
|
|
26
|
+
sourceSite: record.source?.site,
|
|
27
|
+
siteStatus: record.status?.site_status ?? 'unknown',
|
|
28
|
+
siteBadge: record.status?.site_badge ?? String(record.status?.site_status ?? 'unknown').toUpperCase(),
|
|
29
|
+
repoStatus: record.status?.repo_status ?? 'cataloged',
|
|
30
|
+
upstreamStatus: record.status?.upstream_status ?? null,
|
|
31
|
+
upstreamLastUpdate: record.status?.upstream_last_update ?? null,
|
|
32
|
+
cluster: record.cluster ?? 'uncategorized',
|
|
33
|
+
prize: record.prize?.display ?? null,
|
|
34
|
+
familyTags: record.family_tags ?? [],
|
|
35
|
+
relatedProblems: record.related_problems ?? [],
|
|
36
|
+
harnessDepth: record.harness?.depth ?? 'dossier',
|
|
37
|
+
shortStatement: record.statement?.short ?? '',
|
|
38
|
+
formalizationStatus: record.formalization?.status ?? 'unstarted',
|
|
39
|
+
upstreamFormalizedState: record.formalization?.upstream_state ?? null,
|
|
40
|
+
upstreamFormalizedLastUpdate: record.formalization?.upstream_last_update ?? null,
|
|
41
|
+
researchState: record.research_state ?? null,
|
|
42
|
+
upstream: record.upstream ?? null,
|
|
43
|
+
statementPath: path.join(problemDir, statementRelative),
|
|
44
|
+
referencesPath: path.join(problemDir, referencesRelative),
|
|
45
|
+
evidencePath: path.join(problemDir, evidenceRelative),
|
|
46
|
+
formalizationPath: path.join(problemDir, formalizationRelative),
|
|
47
|
+
problemDir,
|
|
48
|
+
problemYamlPath: path.join(problemDir, 'problem.yaml'),
|
|
49
|
+
record,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function loadLocalProblems() {
|
|
54
|
+
if (cachedProblems) {
|
|
55
|
+
return cachedProblems;
|
|
56
|
+
}
|
|
57
|
+
const problemsRoot = path.join(repoRoot, 'problems');
|
|
58
|
+
const directories = fs
|
|
59
|
+
.readdirSync(problemsRoot, { withFileTypes: true })
|
|
60
|
+
.filter((entry) => entry.isDirectory())
|
|
61
|
+
.map((entry) => entry.name)
|
|
62
|
+
.sort((a, b) => Number(a) - Number(b));
|
|
63
|
+
|
|
64
|
+
cachedProblems = directories.map((problemId) => {
|
|
65
|
+
const { problemDir, record } = readProblemRecord(problemId);
|
|
66
|
+
return toCatalogProblem(problemDir, record);
|
|
67
|
+
});
|
|
68
|
+
return cachedProblems;
|
|
69
|
+
}
|
|
69
70
|
|
|
70
71
|
export function listProblems(filters = {}) {
|
|
71
72
|
const cluster = filters.cluster ? String(filters.cluster).toLowerCase() : null;
|
|
72
|
-
|
|
73
|
+
const repoStatus = filters.repoStatus ? String(filters.repoStatus).toLowerCase() : null;
|
|
74
|
+
const harnessDepth = filters.harnessDepth ? String(filters.harnessDepth).toLowerCase() : null;
|
|
75
|
+
const siteStatus = filters.siteStatus ? String(filters.siteStatus).toLowerCase() : null;
|
|
76
|
+
|
|
77
|
+
return loadLocalProblems()
|
|
73
78
|
.filter((entry) => (cluster ? entry.cluster === cluster : true))
|
|
74
|
-
.
|
|
79
|
+
.filter((entry) => (repoStatus ? entry.repoStatus === repoStatus : true))
|
|
80
|
+
.filter((entry) => (harnessDepth ? entry.harnessDepth === harnessDepth : true))
|
|
81
|
+
.filter((entry) => (siteStatus ? entry.siteStatus === siteStatus : true));
|
|
75
82
|
}
|
|
76
83
|
|
|
77
84
|
export function getProblem(problemId) {
|
|
78
|
-
return
|
|
85
|
+
return loadLocalProblems().find((entry) => entry.problemId === String(problemId));
|
|
79
86
|
}
|
|
80
87
|
|
|
81
88
|
export function getCluster(clusterName) {
|
|
@@ -93,6 +100,10 @@ export function getCluster(clusterName) {
|
|
|
93
100
|
}
|
|
94
101
|
|
|
95
102
|
export function listClusters() {
|
|
96
|
-
const names = [...new Set(
|
|
103
|
+
const names = [...new Set(loadLocalProblems().map((entry) => entry.cluster))].sort();
|
|
97
104
|
return names.map((name) => getCluster(name));
|
|
98
105
|
}
|
|
106
|
+
|
|
107
|
+
export function clearCatalogCache() {
|
|
108
|
+
cachedProblems = null;
|
|
109
|
+
}
|
package/src/cli/index.js
CHANGED
|
@@ -1,20 +1,29 @@
|
|
|
1
|
+
import { runBootstrapCommand } from '../commands/bootstrap.js';
|
|
1
2
|
import { runClusterCommand } from '../commands/cluster.js';
|
|
2
3
|
import { runDossierCommand } from '../commands/dossier.js';
|
|
3
4
|
import { runProblemCommand } from '../commands/problem.js';
|
|
5
|
+
import { runScaffoldCommand } from '../commands/scaffold.js';
|
|
6
|
+
import { runUpstreamCommand } from '../commands/upstream.js';
|
|
4
7
|
import { runWorkspaceCommand } from '../commands/workspace.js';
|
|
5
8
|
|
|
6
9
|
function printUsage() {
|
|
7
10
|
console.log('erdos-problems CLI');
|
|
8
11
|
console.log('');
|
|
9
12
|
console.log('Usage:');
|
|
10
|
-
console.log(' erdos problem list [--cluster <name>]');
|
|
13
|
+
console.log(' erdos problem list [--cluster <name>] [--repo-status <status>] [--harness-depth <depth>] [--site-status <status>]');
|
|
11
14
|
console.log(' erdos problem show <id>');
|
|
12
15
|
console.log(' erdos problem use <id>');
|
|
13
16
|
console.log(' erdos problem current');
|
|
17
|
+
console.log(' erdos problem artifacts [<id>] [--json]');
|
|
14
18
|
console.log(' erdos cluster list');
|
|
15
19
|
console.log(' erdos cluster show <name>');
|
|
16
20
|
console.log(' erdos workspace show');
|
|
17
21
|
console.log(' erdos dossier show <id>');
|
|
22
|
+
console.log(' erdos upstream show');
|
|
23
|
+
console.log(' erdos upstream sync [--write-package-snapshot]');
|
|
24
|
+
console.log(' erdos upstream diff [--write-package-report]');
|
|
25
|
+
console.log(' erdos scaffold problem <id> [--dest <path>]');
|
|
26
|
+
console.log(' erdos bootstrap problem <id> [--dest <path>] [--sync-upstream]');
|
|
18
27
|
}
|
|
19
28
|
|
|
20
29
|
const args = process.argv.slice(2);
|
|
@@ -32,6 +41,12 @@ if (!command || command === 'help' || command === '--help') {
|
|
|
32
41
|
exitCode = runWorkspaceCommand(rest);
|
|
33
42
|
} else if (command === 'dossier') {
|
|
34
43
|
exitCode = runDossierCommand(rest);
|
|
44
|
+
} else if (command === 'upstream') {
|
|
45
|
+
exitCode = await runUpstreamCommand(rest);
|
|
46
|
+
} else if (command === 'scaffold') {
|
|
47
|
+
exitCode = runScaffoldCommand(rest);
|
|
48
|
+
} else if (command === 'bootstrap') {
|
|
49
|
+
exitCode = await runBootstrapCommand(rest);
|
|
35
50
|
} else {
|
|
36
51
|
console.error(`Unknown command: ${command}`);
|
|
37
52
|
printUsage();
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { getProblem } from '../atlas/catalog.js';
|
|
3
|
+
import { scaffoldProblem } from '../runtime/problem-artifacts.js';
|
|
4
|
+
import { getWorkspaceProblemScaffoldDir } from '../runtime/paths.js';
|
|
5
|
+
import { setCurrentProblem } from '../runtime/workspace.js';
|
|
6
|
+
import { syncUpstream } from '../upstream/sync.js';
|
|
7
|
+
|
|
8
|
+
function parseBootstrapArgs(args) {
|
|
9
|
+
const [kind, value, ...rest] = args;
|
|
10
|
+
if (kind !== 'problem') {
|
|
11
|
+
return { error: 'Only `erdos bootstrap problem <id>` is supported right now.' };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
let destination = null;
|
|
15
|
+
let syncUpstreamSnapshot = false;
|
|
16
|
+
|
|
17
|
+
for (let index = 0; index < rest.length; index += 1) {
|
|
18
|
+
const token = rest[index];
|
|
19
|
+
if (token === '--dest') {
|
|
20
|
+
destination = rest[index + 1];
|
|
21
|
+
if (!destination) {
|
|
22
|
+
return { error: 'Missing destination path after --dest.' };
|
|
23
|
+
}
|
|
24
|
+
index += 1;
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (token === '--sync-upstream') {
|
|
28
|
+
syncUpstreamSnapshot = true;
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
return { error: `Unknown bootstrap option: ${token}` };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
problemId: value,
|
|
36
|
+
destination,
|
|
37
|
+
syncUpstreamSnapshot,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function runBootstrapCommand(args) {
|
|
42
|
+
if (args.length === 0 || args[0] === 'help' || args[0] === '--help') {
|
|
43
|
+
console.log('Usage:');
|
|
44
|
+
console.log(' erdos bootstrap problem <id> [--dest <path>] [--sync-upstream]');
|
|
45
|
+
return 0;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const parsed = parseBootstrapArgs(args);
|
|
49
|
+
if (parsed.error) {
|
|
50
|
+
console.error(parsed.error);
|
|
51
|
+
return 1;
|
|
52
|
+
}
|
|
53
|
+
if (!parsed.problemId) {
|
|
54
|
+
console.error('Missing problem id.');
|
|
55
|
+
return 1;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const problem = getProblem(parsed.problemId);
|
|
59
|
+
if (!problem) {
|
|
60
|
+
console.error(`Unknown problem: ${parsed.problemId}`);
|
|
61
|
+
return 1;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (parsed.syncUpstreamSnapshot) {
|
|
65
|
+
const syncResult = await syncUpstream();
|
|
66
|
+
console.log(`Workspace upstream snapshot refreshed: ${syncResult.workspacePaths.manifestPath}`);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
setCurrentProblem(problem.problemId);
|
|
70
|
+
const destination = parsed.destination
|
|
71
|
+
? path.resolve(parsed.destination)
|
|
72
|
+
: getWorkspaceProblemScaffoldDir(problem.problemId);
|
|
73
|
+
const result = scaffoldProblem(problem, destination);
|
|
74
|
+
|
|
75
|
+
console.log(`Bootstrapped problem ${problem.problemId} (${problem.title})`);
|
|
76
|
+
console.log(`Active problem: ${problem.problemId}`);
|
|
77
|
+
console.log(`Scaffold dir: ${result.destination}`);
|
|
78
|
+
console.log(`Artifacts copied: ${result.copiedArtifacts.length}`);
|
|
79
|
+
console.log(`Upstream record included: ${result.inventory.upstreamRecordIncluded ? 'yes' : 'no'}`);
|
|
80
|
+
return 0;
|
|
81
|
+
}
|
package/src/commands/dossier.js
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
|
-
import path from 'node:path';
|
|
3
2
|
import { getProblem } from '../atlas/catalog.js';
|
|
4
|
-
import { getProblemDir } from '../runtime/paths.js';
|
|
5
3
|
import { readCurrentProblem } from '../runtime/workspace.js';
|
|
6
4
|
|
|
7
|
-
const sections = [
|
|
5
|
+
const sections = [
|
|
6
|
+
['problem.yaml', 'problemYamlPath'],
|
|
7
|
+
['STATEMENT.md', 'statementPath'],
|
|
8
|
+
['REFERENCES.md', 'referencesPath'],
|
|
9
|
+
['EVIDENCE.md', 'evidencePath'],
|
|
10
|
+
['FORMALIZATION.md', 'formalizationPath'],
|
|
11
|
+
];
|
|
8
12
|
|
|
9
13
|
export function runDossierCommand(args) {
|
|
10
14
|
const [subcommand, value] = args;
|
|
@@ -32,20 +36,24 @@ export function runDossierCommand(args) {
|
|
|
32
36
|
return 1;
|
|
33
37
|
}
|
|
34
38
|
|
|
35
|
-
const problemDir = getProblemDir(problem.problemId);
|
|
36
39
|
console.log(`${problem.displayName} dossier`);
|
|
37
|
-
console.log(`Directory: ${problemDir}`);
|
|
40
|
+
console.log(`Directory: ${problem.problemDir}`);
|
|
38
41
|
console.log('Sections:');
|
|
39
|
-
for (const
|
|
40
|
-
const filePath =
|
|
42
|
+
for (const [label, key] of sections) {
|
|
43
|
+
const filePath = problem[key];
|
|
41
44
|
const exists = fs.existsSync(filePath);
|
|
42
|
-
console.log(`- ${
|
|
45
|
+
console.log(`- ${label}: ${exists ? 'present' : 'missing'}`);
|
|
43
46
|
}
|
|
44
|
-
|
|
45
|
-
|
|
47
|
+
console.log('');
|
|
48
|
+
console.log('Canonical metadata:');
|
|
49
|
+
console.log(`- cluster: ${problem.cluster}`);
|
|
50
|
+
console.log(`- repo status: ${problem.repoStatus}`);
|
|
51
|
+
console.log(`- harness depth: ${problem.harnessDepth}`);
|
|
52
|
+
console.log(`- upstream number: ${problem.upstream?.number ?? '(unset)'}`);
|
|
53
|
+
if (fs.existsSync(problem.statementPath)) {
|
|
46
54
|
console.log('');
|
|
47
55
|
console.log('Statement preview:');
|
|
48
|
-
console.log(fs.readFileSync(statementPath, 'utf8').trim());
|
|
56
|
+
console.log(fs.readFileSync(problem.statementPath, 'utf8').trim());
|
|
49
57
|
}
|
|
50
58
|
return 0;
|
|
51
59
|
}
|
package/src/commands/problem.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getProblem, listProblems } from '../atlas/catalog.js';
|
|
2
|
+
import { getProblemArtifactInventory } from '../runtime/problem-artifacts.js';
|
|
2
3
|
import { readCurrentProblem, setCurrentProblem } from '../runtime/workspace.js';
|
|
3
4
|
|
|
4
5
|
function parseListFilters(args) {
|
|
@@ -14,20 +15,70 @@ function parseListFilters(args) {
|
|
|
14
15
|
index += 1;
|
|
15
16
|
continue;
|
|
16
17
|
}
|
|
18
|
+
if (token === '--repo-status') {
|
|
19
|
+
const repoStatus = args[index + 1];
|
|
20
|
+
if (!repoStatus) {
|
|
21
|
+
return { error: 'Missing repo status after --repo-status.' };
|
|
22
|
+
}
|
|
23
|
+
filters.repoStatus = repoStatus;
|
|
24
|
+
index += 1;
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (token === '--harness-depth') {
|
|
28
|
+
const harnessDepth = args[index + 1];
|
|
29
|
+
if (!harnessDepth) {
|
|
30
|
+
return { error: 'Missing harness depth after --harness-depth.' };
|
|
31
|
+
}
|
|
32
|
+
filters.harnessDepth = harnessDepth;
|
|
33
|
+
index += 1;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (token === '--site-status') {
|
|
37
|
+
const siteStatus = args[index + 1];
|
|
38
|
+
if (!siteStatus) {
|
|
39
|
+
return { error: 'Missing site status after --site-status.' };
|
|
40
|
+
}
|
|
41
|
+
filters.siteStatus = siteStatus;
|
|
42
|
+
index += 1;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
17
45
|
return { error: `Unknown list option: ${token}` };
|
|
18
46
|
}
|
|
19
47
|
return { filters };
|
|
20
48
|
}
|
|
21
49
|
|
|
50
|
+
function parseArtifactArgs(args) {
|
|
51
|
+
const parsed = {
|
|
52
|
+
problemId: null,
|
|
53
|
+
asJson: false,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
57
|
+
const token = args[index];
|
|
58
|
+
if (token === '--json') {
|
|
59
|
+
parsed.asJson = true;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
if (!parsed.problemId) {
|
|
63
|
+
parsed.problemId = token;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
return { error: `Unknown artifact option: ${token}` };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return parsed;
|
|
70
|
+
}
|
|
71
|
+
|
|
22
72
|
function printProblemTable(rows, activeProblem) {
|
|
23
|
-
console.log('ID Site Repo Cluster
|
|
73
|
+
console.log('ID Site Repo Cluster Depth Active Title');
|
|
24
74
|
for (const row of rows) {
|
|
25
75
|
const id = row.problemId.padEnd(4, ' ');
|
|
26
76
|
const site = row.siteStatus.padEnd(6, ' ');
|
|
27
77
|
const repo = row.repoStatus.padEnd(10, ' ');
|
|
28
|
-
const cluster = row.cluster.padEnd(
|
|
78
|
+
const cluster = row.cluster.padEnd(15, ' ');
|
|
79
|
+
const depth = row.harnessDepth.padEnd(8, ' ');
|
|
29
80
|
const active = (row.problemId === activeProblem ? '*' : '-').padEnd(7, ' ');
|
|
30
|
-
console.log(`${id} ${site} ${repo} ${cluster} ${active} ${row.title}`);
|
|
81
|
+
console.log(`${id} ${site} ${repo} ${cluster} ${depth} ${active} ${row.title}`);
|
|
31
82
|
}
|
|
32
83
|
}
|
|
33
84
|
|
|
@@ -36,31 +87,68 @@ function printProblem(problem) {
|
|
|
36
87
|
console.log(`Title: ${problem.title}`);
|
|
37
88
|
console.log(`Source: ${problem.sourceUrl}`);
|
|
38
89
|
console.log(`Site status: ${problem.siteStatus}`);
|
|
90
|
+
console.log(`Site badge: ${problem.siteBadge ?? problem.siteStatus}`);
|
|
39
91
|
console.log(`Repo status: ${problem.repoStatus}`);
|
|
40
92
|
console.log(`Cluster: ${problem.cluster}`);
|
|
41
93
|
console.log(`Harness depth: ${problem.harnessDepth}`);
|
|
94
|
+
console.log(`Prize: ${problem.prize ?? '(none)'}`);
|
|
42
95
|
console.log(`Formalization: ${problem.formalizationStatus}`);
|
|
96
|
+
console.log(`Upstream formalized: ${problem.upstreamFormalizedState ?? '(unknown)'}`);
|
|
97
|
+
console.log(`Upstream last update: ${problem.upstreamLastUpdate ?? '(unknown)'}`);
|
|
43
98
|
console.log(`Related: ${problem.relatedProblems.join(', ') || '(none)'}`);
|
|
44
99
|
console.log(`Tags: ${problem.familyTags.join(', ') || '(none)'}`);
|
|
45
100
|
console.log(`Statement: ${problem.shortStatement}`);
|
|
46
101
|
if (problem.researchState) {
|
|
47
102
|
console.log('Research state:');
|
|
48
|
-
console.log(` open problem: ${problem.researchState.
|
|
49
|
-
console.log(` active route: ${problem.researchState.
|
|
50
|
-
console.log(` route breakthrough: ${problem.researchState.
|
|
51
|
-
console.log(` problem solved: ${problem.researchState.
|
|
103
|
+
console.log(` open problem: ${problem.researchState.open_problem ? 'yes' : 'no'}`);
|
|
104
|
+
console.log(` active route: ${problem.researchState.active_route}`);
|
|
105
|
+
console.log(` route breakthrough: ${problem.researchState.route_breakthrough ? 'yes' : 'no'}`);
|
|
106
|
+
console.log(` problem solved: ${problem.researchState.problem_solved ? 'yes' : 'no'}`);
|
|
107
|
+
}
|
|
108
|
+
if (problem.upstream) {
|
|
109
|
+
console.log('Upstream provenance:');
|
|
110
|
+
console.log(` repo: ${problem.upstream.repo}`);
|
|
111
|
+
console.log(` data file: ${problem.upstream.data_file}`);
|
|
112
|
+
console.log(` number: ${problem.upstream.number}`);
|
|
52
113
|
}
|
|
53
114
|
}
|
|
54
115
|
|
|
116
|
+
function printArtifactInventory(problem, inventory, asJson) {
|
|
117
|
+
if (asJson) {
|
|
118
|
+
console.log(JSON.stringify(inventory, null, 2));
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
console.log(`${problem.displayName} canonical artifacts`);
|
|
123
|
+
console.log(`Problem directory: ${inventory.problemDir}`);
|
|
124
|
+
console.log(`Source: ${inventory.sourceUrl}`);
|
|
125
|
+
console.log('Canonical files:');
|
|
126
|
+
for (const artifact of inventory.canonicalArtifacts) {
|
|
127
|
+
console.log(`- ${artifact.label}: ${artifact.exists ? 'present' : 'missing'} (${artifact.path})`);
|
|
128
|
+
}
|
|
129
|
+
if (inventory.packContext) {
|
|
130
|
+
console.log(`- ${inventory.packContext.label}: ${inventory.packContext.exists ? 'present' : 'missing'} (${inventory.packContext.path})`);
|
|
131
|
+
}
|
|
132
|
+
if (inventory.upstreamSnapshot) {
|
|
133
|
+
console.log('Upstream snapshot:');
|
|
134
|
+
console.log(`- kind: ${inventory.upstreamSnapshot.kind}`);
|
|
135
|
+
console.log(`- manifest: ${inventory.upstreamSnapshot.manifestPath}`);
|
|
136
|
+
console.log(`- index: ${inventory.upstreamSnapshot.indexPath}`);
|
|
137
|
+
console.log(`- commit: ${inventory.upstreamSnapshot.upstreamCommit ?? '(unknown)'}`);
|
|
138
|
+
}
|
|
139
|
+
console.log(`Upstream record available: ${inventory.upstreamRecordIncluded ? 'yes' : 'no'}`);
|
|
140
|
+
}
|
|
141
|
+
|
|
55
142
|
export function runProblemCommand(args) {
|
|
56
143
|
const [subcommand, value, ...rest] = args;
|
|
57
144
|
|
|
58
145
|
if (!subcommand || subcommand === 'help' || subcommand === '--help') {
|
|
59
146
|
console.log('Usage:');
|
|
60
|
-
console.log(' erdos problem list [--cluster <name>]');
|
|
147
|
+
console.log(' erdos problem list [--cluster <name>] [--repo-status <status>] [--harness-depth <depth>] [--site-status <status>]');
|
|
61
148
|
console.log(' erdos problem show <id>');
|
|
62
149
|
console.log(' erdos problem use <id>');
|
|
63
150
|
console.log(' erdos problem current');
|
|
151
|
+
console.log(' erdos problem artifacts [<id>] [--json]');
|
|
64
152
|
return 0;
|
|
65
153
|
}
|
|
66
154
|
|
|
@@ -119,6 +207,27 @@ export function runProblemCommand(args) {
|
|
|
119
207
|
return 0;
|
|
120
208
|
}
|
|
121
209
|
|
|
210
|
+
if (subcommand === 'artifacts') {
|
|
211
|
+
const parsed = parseArtifactArgs([value, ...rest].filter(Boolean));
|
|
212
|
+
if (parsed.error) {
|
|
213
|
+
console.error(parsed.error);
|
|
214
|
+
return 1;
|
|
215
|
+
}
|
|
216
|
+
const problemId = parsed.problemId ?? readCurrentProblem();
|
|
217
|
+
if (!problemId) {
|
|
218
|
+
console.error('Missing problem id and no active problem is selected.');
|
|
219
|
+
return 1;
|
|
220
|
+
}
|
|
221
|
+
const problem = getProblem(problemId);
|
|
222
|
+
if (!problem) {
|
|
223
|
+
console.error(`Unknown problem: ${problemId}`);
|
|
224
|
+
return 1;
|
|
225
|
+
}
|
|
226
|
+
const inventory = getProblemArtifactInventory(problem);
|
|
227
|
+
printArtifactInventory(problem, inventory, parsed.asJson);
|
|
228
|
+
return 0;
|
|
229
|
+
}
|
|
230
|
+
|
|
122
231
|
console.error(`Unknown problem subcommand: ${subcommand}`);
|
|
123
232
|
return 1;
|
|
124
233
|
}
|