open-research-protocol 0.4.18 → 0.4.19
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 +6 -1
- package/docs/PROFILE_PACKS.md +8 -0
- package/package.json +1 -1
- package/packs/erdos-open-problems/pack.yml +54 -0
- package/packs/external-pr-governance/pack.yml +17 -0
- package/packs/issue-smashers/pack.yml +25 -0
- package/scripts/orp-pack-install.py +90 -11
- package/spec/v1/profile-pack.schema.json +48 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# ORP — Open Research Protocol
|
|
2
2
|
|
|
3
|
-
Maintained by Fractal Research Group (
|
|
3
|
+
Maintained by SproutSeeds. Research stewardship: Fractal Research Group ([frg.earth](https://frg.earth)).
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/open-research-protocol)
|
|
6
6
|
[](https://www.npmjs.com/package/open-research-protocol)
|
|
@@ -443,6 +443,11 @@ If you are using ORP normally, prefer:
|
|
|
443
443
|
Reach for `orp pack ...` when you are doing advanced installs, ORP maintenance,
|
|
444
444
|
or direct domain-template work.
|
|
445
445
|
|
|
446
|
+
Pack installation is pack-owned: `pack.yml` can describe installable
|
|
447
|
+
components, default includes, dependency checks, and report naming. That lets
|
|
448
|
+
ORP consume repo-owned external packs through `--pack-path` without baking
|
|
449
|
+
domain-specific install rules into ORP core.
|
|
450
|
+
|
|
446
451
|
Install pack configs into a target repo (recommended):
|
|
447
452
|
|
|
448
453
|
```bash
|
package/docs/PROFILE_PACKS.md
CHANGED
|
@@ -39,6 +39,7 @@ Canonical fields:
|
|
|
39
39
|
- `pack_id`: stable id
|
|
40
40
|
- `name`, `version`, `description`
|
|
41
41
|
- `orp_version_min`: optional compatibility floor
|
|
42
|
+
- `install`: optional install contract for `orp pack install`
|
|
42
43
|
- `variables`: render-time variables (for example `TARGET_REPO_ROOT`)
|
|
43
44
|
- `templates`: available config templates
|
|
44
45
|
|
|
@@ -80,6 +81,10 @@ orp pack fetch \
|
|
|
80
81
|
--install-target /path/to/repo
|
|
81
82
|
```
|
|
82
83
|
|
|
84
|
+
Repo-owned local packs can also be installed directly with `--pack-path` as
|
|
85
|
+
long as their `pack.yml` includes an `install` block describing components,
|
|
86
|
+
default includes, and dependency-audit paths.
|
|
87
|
+
|
|
83
88
|
This installs rendered config files and writes a dependency audit report:
|
|
84
89
|
|
|
85
90
|
- `./orp.erdos-catalog-sync.yml`
|
|
@@ -218,6 +223,9 @@ orp erdos sync --problem-id 857 --problem-id 20
|
|
|
218
223
|
- Packs can live in this repo (`packs/`) or external repos.
|
|
219
224
|
- Users can copy/install packs without changing ORP core.
|
|
220
225
|
- Version packs independently (for example `0.1.0`, `0.2.0`).
|
|
226
|
+
- Repo-owned packs can ship their own install metadata in `pack.yml`, so ORP
|
|
227
|
+
can install external domain packs without hardcoding those domains into ORP
|
|
228
|
+
core.
|
|
221
229
|
|
|
222
230
|
## Quality guidance
|
|
223
231
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "open-research-protocol",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.19",
|
|
4
4
|
"description": "ORP CLI (Open Research Protocol): workspace ledgers, secrets, scheduling, governed execution, and agent-friendly research workflows.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Fractal Research Group <cody@frg.earth>",
|
|
@@ -129,3 +129,57 @@ templates:
|
|
|
129
129
|
output_hint: orp.erdos-catalog-sync.yml
|
|
130
130
|
default_profiles:
|
|
131
131
|
- erdos_catalog_sync_active
|
|
132
|
+
|
|
133
|
+
install:
|
|
134
|
+
default_includes:
|
|
135
|
+
- catalog
|
|
136
|
+
- live_compare
|
|
137
|
+
- problem857
|
|
138
|
+
report_name: orp.erdos.pack-install-report.md
|
|
139
|
+
components:
|
|
140
|
+
catalog:
|
|
141
|
+
template_id: erdos_problems_catalog_sync
|
|
142
|
+
output_name: orp.erdos-catalog-sync.yml
|
|
143
|
+
description: Erdos catalog sync (all/open/closed/active snapshots).
|
|
144
|
+
live_compare:
|
|
145
|
+
template_id: sunflower_live_compare_suite
|
|
146
|
+
output_name: orp.erdos-live-compare.yml
|
|
147
|
+
description: Side-by-side atomic-board compare for Problems 857/20/367.
|
|
148
|
+
required_paths:
|
|
149
|
+
- analysis/problem857_counting_gateboard.json
|
|
150
|
+
- analysis/problem20_k3_gateboard.json
|
|
151
|
+
- analysis/problem367_sharp_gateboard.json
|
|
152
|
+
- scripts/problem857_ops_board.py
|
|
153
|
+
- scripts/problem20_ops_board.py
|
|
154
|
+
- scripts/problem367_ops_board.py
|
|
155
|
+
- scripts/frontier_status.py
|
|
156
|
+
problem857:
|
|
157
|
+
template_id: sunflower_problem857_discovery
|
|
158
|
+
output_name: orp.erdos-problem857.yml
|
|
159
|
+
description: Problem 857 discovery profile (board refresh/ready/spec/lean/frontier).
|
|
160
|
+
required_paths:
|
|
161
|
+
- analysis/problem857_counting_gateboard.json
|
|
162
|
+
- docs/PROBLEM857_COUNTING_OPS_BOARD.md
|
|
163
|
+
- orchestrator/v2/scopes/problem_857.yaml
|
|
164
|
+
- orchestrator/problem857_public_spec_check.py
|
|
165
|
+
- scripts/problem857_ops_board.py
|
|
166
|
+
- scripts/frontier_status.py
|
|
167
|
+
- sunflower_lean
|
|
168
|
+
governance:
|
|
169
|
+
template_id: sunflower_mathlib_pr_governance
|
|
170
|
+
output_name: orp.erdos-mathlib-pr-governance.yml
|
|
171
|
+
description: Mathlib PR governance profile set (pre-open, draft-readiness, full flow).
|
|
172
|
+
required_paths:
|
|
173
|
+
- docs/MATHLIB_SUBMISSION_CHECKLIST.md
|
|
174
|
+
- docs/MATHLIB_DRAFT_PR_TEMPLATE.md
|
|
175
|
+
- docs/MATHLIB_ISSUE_VIABILITY_GATE.md
|
|
176
|
+
- docs/UPSTREAM_PR_LANE.md
|
|
177
|
+
- analysis/UPSTREAM_PR_PLAN.yaml
|
|
178
|
+
- scripts/upstream-pr-plan.py
|
|
179
|
+
- scripts/upstream-pr-lane.sh
|
|
180
|
+
- scripts/mathlib-issue-viability-gate.py
|
|
181
|
+
- scripts/mathlib-naturality-snippet.sh
|
|
182
|
+
- scripts/mathlib-issue-local-gate.sh
|
|
183
|
+
- scripts/mathlib-tighten-fine-tooth-gate.sh
|
|
184
|
+
- scripts/mathlib-ready-to-draft-gate.sh
|
|
185
|
+
- scripts/mathlib-pr-body-preflight.py
|
|
@@ -144,3 +144,20 @@ templates:
|
|
|
144
144
|
output_hint: orp.external-pr-feedback-hardening.yml
|
|
145
145
|
default_profiles:
|
|
146
146
|
- external_feedback_hardening
|
|
147
|
+
|
|
148
|
+
install:
|
|
149
|
+
default_includes:
|
|
150
|
+
- governance
|
|
151
|
+
- feedback_hardening
|
|
152
|
+
report_name: orp.external-pr.pack-install-report.md
|
|
153
|
+
components:
|
|
154
|
+
governance:
|
|
155
|
+
template_id: oss_pr_governance
|
|
156
|
+
output_name: orp.external-pr-governance.yml
|
|
157
|
+
description: Generic external contribution governance profiles (watch/select, pre-open, local-readiness, draft transition, draft lifecycle, full flow).
|
|
158
|
+
required_paths:
|
|
159
|
+
- analysis/PR_DRAFT_BODY.md
|
|
160
|
+
feedback_hardening:
|
|
161
|
+
template_id: oss_feedback_hardening
|
|
162
|
+
output_name: orp.external-pr-feedback-hardening.yml
|
|
163
|
+
description: Generic maintainer-feedback hardening profile.
|
|
@@ -176,3 +176,28 @@ templates:
|
|
|
176
176
|
output_hint: orp.issue-smashers-feedback-hardening.yml
|
|
177
177
|
default_profiles:
|
|
178
178
|
- issue_smashers_feedback_hardening
|
|
179
|
+
|
|
180
|
+
install:
|
|
181
|
+
default_includes:
|
|
182
|
+
- workspace
|
|
183
|
+
- feedback_hardening
|
|
184
|
+
report_name: orp.issue-smashers.pack-install-report.md
|
|
185
|
+
components:
|
|
186
|
+
workspace:
|
|
187
|
+
template_id: issue_smashers_workspace
|
|
188
|
+
output_name: orp.issue-smashers.yml
|
|
189
|
+
description: Opinionated issue-smashers workspace and external contribution governance profiles.
|
|
190
|
+
required_paths:
|
|
191
|
+
- issue-smashers/README.md
|
|
192
|
+
- issue-smashers/WORKSPACE_RULES.md
|
|
193
|
+
- issue-smashers/setup-issue-smashers.sh
|
|
194
|
+
- issue-smashers/analysis/ISSUE_SMASHERS_WATCHLIST.json
|
|
195
|
+
- issue-smashers/analysis/ISSUE_SMASHERS_STATUS.md
|
|
196
|
+
- issue-smashers/analysis/PR_DRAFT_BODY.md
|
|
197
|
+
feedback_hardening:
|
|
198
|
+
template_id: issue_smashers_feedback_hardening
|
|
199
|
+
output_name: orp.issue-smashers-feedback-hardening.yml
|
|
200
|
+
description: Issue-smashers maintainer-feedback hardening profile.
|
|
201
|
+
required_paths:
|
|
202
|
+
- issue-smashers/WORKSPACE_RULES.md
|
|
203
|
+
- issue-smashers/analysis/ISSUE_SMASHERS_STATUS.md
|
|
@@ -24,7 +24,7 @@ from typing import Any
|
|
|
24
24
|
import yaml
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
LEGACY_PACK_SPECS: dict[str, dict[str, Any]] = {
|
|
28
28
|
"erdos-open-problems": {
|
|
29
29
|
"default_includes": ["catalog", "live_compare", "problem857"],
|
|
30
30
|
"report_name": "orp.erdos.pack-install-report.md",
|
|
@@ -1267,18 +1267,99 @@ def _load_yaml(path: Path) -> dict[str, Any]:
|
|
|
1267
1267
|
return payload
|
|
1268
1268
|
|
|
1269
1269
|
|
|
1270
|
-
def
|
|
1271
|
-
spec =
|
|
1270
|
+
def _legacy_pack_spec(pack_id: str) -> dict[str, Any]:
|
|
1271
|
+
spec = LEGACY_PACK_SPECS.get(pack_id)
|
|
1272
1272
|
if not isinstance(spec, dict):
|
|
1273
1273
|
raise RuntimeError(f"unsupported pack for install flow: {pack_id}")
|
|
1274
1274
|
return spec
|
|
1275
1275
|
|
|
1276
1276
|
|
|
1277
|
-
def
|
|
1278
|
-
|
|
1277
|
+
def _pack_install_spec(pack_meta: dict[str, Any], pack_id: str) -> dict[str, Any]:
|
|
1278
|
+
install = pack_meta.get("install")
|
|
1279
|
+
if isinstance(install, dict):
|
|
1280
|
+
return install
|
|
1281
|
+
return _legacy_pack_spec(pack_id)
|
|
1282
|
+
|
|
1283
|
+
|
|
1284
|
+
def _pack_templates(pack_meta: dict[str, Any]) -> dict[str, dict[str, Any]]:
|
|
1285
|
+
raw = pack_meta.get("templates", {})
|
|
1286
|
+
if not isinstance(raw, dict):
|
|
1287
|
+
return {}
|
|
1288
|
+
out: dict[str, dict[str, Any]] = {}
|
|
1289
|
+
for key, value in raw.items():
|
|
1290
|
+
if isinstance(key, str) and isinstance(value, dict):
|
|
1291
|
+
out[key] = value
|
|
1292
|
+
return out
|
|
1293
|
+
|
|
1294
|
+
|
|
1295
|
+
def _normalize_install_component(
|
|
1296
|
+
component_key: str,
|
|
1297
|
+
raw_component: dict[str, Any],
|
|
1298
|
+
*,
|
|
1299
|
+
templates: dict[str, dict[str, Any]],
|
|
1300
|
+
) -> dict[str, Any]:
|
|
1301
|
+
template_id = str(raw_component.get("template_id", "")).strip()
|
|
1302
|
+
if not template_id:
|
|
1303
|
+
raise RuntimeError(f"install component missing template_id: {component_key}")
|
|
1304
|
+
|
|
1305
|
+
template_meta = templates.get(template_id)
|
|
1306
|
+
if not isinstance(template_meta, dict):
|
|
1307
|
+
raise RuntimeError(
|
|
1308
|
+
f"install component {component_key} references unknown template_id: {template_id}"
|
|
1309
|
+
)
|
|
1310
|
+
|
|
1311
|
+
output_name = str(raw_component.get("output_name") or template_meta.get("output_hint") or "").strip()
|
|
1312
|
+
if not output_name:
|
|
1313
|
+
raise RuntimeError(
|
|
1314
|
+
f"install component {component_key} is missing output_name and template {template_id} has no output_hint"
|
|
1315
|
+
)
|
|
1316
|
+
|
|
1317
|
+
description = str(raw_component.get("description") or template_meta.get("description") or "").strip()
|
|
1318
|
+
required_paths_raw = raw_component.get("required_paths", [])
|
|
1319
|
+
if required_paths_raw is None:
|
|
1320
|
+
required_paths: list[str] = []
|
|
1321
|
+
elif isinstance(required_paths_raw, list):
|
|
1322
|
+
required_paths = [str(path) for path in required_paths_raw]
|
|
1323
|
+
else:
|
|
1324
|
+
raise RuntimeError(f"install component required_paths must be a list: {component_key}")
|
|
1325
|
+
|
|
1326
|
+
return {
|
|
1327
|
+
"template_id": template_id,
|
|
1328
|
+
"output_name": output_name,
|
|
1329
|
+
"description": description,
|
|
1330
|
+
"required_paths": required_paths,
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
|
|
1334
|
+
def _pack_components(pack_meta: dict[str, Any], pack_id: str) -> dict[str, dict[str, Any]]:
|
|
1335
|
+
install = _pack_install_spec(pack_meta, pack_id)
|
|
1336
|
+
components = install.get("components", {})
|
|
1279
1337
|
if not isinstance(components, dict) or not components:
|
|
1280
1338
|
raise RuntimeError(f"pack has no installable components: {pack_id}")
|
|
1281
|
-
|
|
1339
|
+
|
|
1340
|
+
templates = _pack_templates(pack_meta)
|
|
1341
|
+
out: dict[str, dict[str, Any]] = {}
|
|
1342
|
+
for key, value in components.items():
|
|
1343
|
+
if not isinstance(key, str) or not isinstance(value, dict):
|
|
1344
|
+
raise RuntimeError(f"invalid install component entry in pack {pack_id}: {key!r}")
|
|
1345
|
+
out[key] = _normalize_install_component(key, value, templates=templates)
|
|
1346
|
+
return out
|
|
1347
|
+
|
|
1348
|
+
|
|
1349
|
+
def _pack_default_includes(pack_meta: dict[str, Any], pack_id: str) -> list[str]:
|
|
1350
|
+
install = _pack_install_spec(pack_meta, pack_id)
|
|
1351
|
+
raw = install.get("default_includes", [])
|
|
1352
|
+
if not isinstance(raw, list):
|
|
1353
|
+
return []
|
|
1354
|
+
return [str(x) for x in raw if isinstance(x, str)]
|
|
1355
|
+
|
|
1356
|
+
|
|
1357
|
+
def _pack_report_name(pack_meta: dict[str, Any], pack_id: str) -> str:
|
|
1358
|
+
install = _pack_install_spec(pack_meta, pack_id)
|
|
1359
|
+
raw = install.get("report_name")
|
|
1360
|
+
if isinstance(raw, str) and raw.strip():
|
|
1361
|
+
return raw.strip()
|
|
1362
|
+
return f"orp.{pack_id}.pack-install-report.md"
|
|
1282
1363
|
|
|
1283
1364
|
|
|
1284
1365
|
def _validate_var(raw: str) -> str:
|
|
@@ -2153,15 +2234,13 @@ def main() -> int:
|
|
|
2153
2234
|
pack_id = str(pack_meta.get("pack_id", args.pack_id))
|
|
2154
2235
|
pack_version = str(pack_meta.get("version", "unknown"))
|
|
2155
2236
|
generated_at_utc = _now_utc()
|
|
2156
|
-
components = _pack_components(pack_id)
|
|
2237
|
+
components = _pack_components(pack_meta, pack_id)
|
|
2157
2238
|
effective_vars = _vars_map(pack_meta, list(args.var or []))
|
|
2158
2239
|
problem857_source_mode = _problem857_source_mode(effective_vars)
|
|
2159
2240
|
|
|
2160
2241
|
includes = list(args.include or [])
|
|
2161
2242
|
if not includes:
|
|
2162
|
-
|
|
2163
|
-
if isinstance(default_includes, list):
|
|
2164
|
-
includes = [str(x) for x in default_includes if isinstance(x, str)]
|
|
2243
|
+
includes = _pack_default_includes(pack_meta, pack_id)
|
|
2165
2244
|
if not includes:
|
|
2166
2245
|
includes = sorted(components.keys())
|
|
2167
2246
|
|
|
@@ -2227,7 +2306,7 @@ def main() -> int:
|
|
|
2227
2306
|
else:
|
|
2228
2307
|
report_path = report_path.resolve()
|
|
2229
2308
|
else:
|
|
2230
|
-
report_name =
|
|
2309
|
+
report_name = _pack_report_name(pack_meta, pack_id)
|
|
2231
2310
|
report_path = (target_repo_root / report_name).resolve()
|
|
2232
2311
|
|
|
2233
2312
|
_write_report(
|
|
@@ -34,6 +34,9 @@
|
|
|
34
34
|
"orp_version_min": {
|
|
35
35
|
"type": "string"
|
|
36
36
|
},
|
|
37
|
+
"install": {
|
|
38
|
+
"$ref": "#/$defs/install"
|
|
39
|
+
},
|
|
37
40
|
"variables": {
|
|
38
41
|
"type": "object",
|
|
39
42
|
"additionalProperties": {
|
|
@@ -90,6 +93,51 @@
|
|
|
90
93
|
}
|
|
91
94
|
}
|
|
92
95
|
}
|
|
96
|
+
},
|
|
97
|
+
"install": {
|
|
98
|
+
"type": "object",
|
|
99
|
+
"additionalProperties": false,
|
|
100
|
+
"properties": {
|
|
101
|
+
"default_includes": {
|
|
102
|
+
"type": "array",
|
|
103
|
+
"items": {
|
|
104
|
+
"type": "string"
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
"report_name": {
|
|
108
|
+
"type": "string"
|
|
109
|
+
},
|
|
110
|
+
"components": {
|
|
111
|
+
"type": "object",
|
|
112
|
+
"additionalProperties": {
|
|
113
|
+
"$ref": "#/$defs/installComponent"
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
"installComponent": {
|
|
119
|
+
"type": "object",
|
|
120
|
+
"additionalProperties": false,
|
|
121
|
+
"required": [
|
|
122
|
+
"template_id"
|
|
123
|
+
],
|
|
124
|
+
"properties": {
|
|
125
|
+
"template_id": {
|
|
126
|
+
"type": "string"
|
|
127
|
+
},
|
|
128
|
+
"output_name": {
|
|
129
|
+
"type": "string"
|
|
130
|
+
},
|
|
131
|
+
"description": {
|
|
132
|
+
"type": "string"
|
|
133
|
+
},
|
|
134
|
+
"required_paths": {
|
|
135
|
+
"type": "array",
|
|
136
|
+
"items": {
|
|
137
|
+
"type": "string"
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
93
141
|
}
|
|
94
142
|
}
|
|
95
143
|
}
|