open-research-protocol 0.4.12 → 0.4.14

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 CHANGED
@@ -59,6 +59,7 @@ ORP should feel like one CLI with built-in abilities:
59
59
  - `erdos` for Erdos-specific data and workflow support
60
60
  - `report` and `packet` for ORP artifacts
61
61
  - `compute` for targeted compute admission, local execution, and paid approval gating
62
+ - `frontier` for exact live-point control, active-milestone views, near-term checklist management, and farther version-stack planning
62
63
 
63
64
  The `pack` layer still exists, but it is now an advanced/internal surface rather
64
65
  than the main product story.
@@ -150,6 +151,16 @@ orp compute decide --input orp.compute.json --json
150
151
  orp compute decide --project-map orp.compute-map.json --point-id adult-vs-developmental-rgc-opponent --json
151
152
  orp compute run-local --input orp.compute.json --task orp.compute.task.json --json
152
153
  orp compute run-local --project-map orp.compute-map.json --point-id adult-vs-developmental-rgc-opponent --task orp.compute.task.json --json
154
+ orp frontier init --program-id ocular-controller --json
155
+ orp frontier add-version --id v10 --label "Certified generalization arc" --json
156
+ orp frontier add-milestone --version v10 --id v10.3 --label "Figure specification and data contract freeze" --band exact --json
157
+ orp frontier add-phase --milestone v10.3 --id 395 --label "Figure specification and data contract freeze" --compute-point-id adult-vs-developmental-rgc-opponent --allowed-rung local-4090 --paid-requires-user-approval --json
158
+ orp frontier set-live --version v10 --milestone v10.3 --phase 395 --band exact --next-action "Execute Phase 395" --json
159
+ orp frontier state --json
160
+ orp frontier roadmap --json
161
+ orp frontier checklist --json
162
+ orp frontier stack --json
163
+ orp frontier doctor --json
153
164
  orp report summary --json
154
165
  ```
155
166
 
@@ -160,6 +171,12 @@ These surfaces are meant to help automated systems discover ORP quickly:
160
171
  - `orp auth ...`, `orp ideas ...`, `orp world ...`, `orp checkpoint ...`, `orp runner ...`, and `orp agent ...` expose the hosted workspace surface directly through ORP
161
172
  - `orp compute ...` exposes targeted-compute admission, local execution, and paid-approval gating through a stable ORP wrapper surface
162
173
  - `orp compute ...` can now consume either a raw compute packet input or a repo-declared `breakthroughs` project compute map plus a compute-point id
174
+ - `orp frontier ...` exposes the four-layer planning split directly in ORP:
175
+ - exact live point
176
+ - exact active milestone roadmap
177
+ - near-term structured checklist
178
+ - farther major-version stack
179
+ - frontier phases can carry bounded compute hooks, so a repo's active frontier can surface where targeted compute belongs without letting compute drift outside the main research loop
163
180
  - `orp youtube inspect ...` exposes public YouTube metadata plus full transcript ingestion through a stable ORP artifact shape for agent use when caption tracks are available
164
181
  - `orp init`, `orp status`, `orp branch start`, `orp checkpoint create`, `orp backup`, `orp ready`, `orp doctor`, and `orp cleanup` expose the local-first repo governance surface directly through ORP
165
182
  - `orp discover ...` exposes profile-based GitHub scanning as a built-in ORP ability
package/cli/orp.py CHANGED
@@ -114,6 +114,8 @@ DEFAULT_DISCOVER_PROFILE = "orp.profile.default.json"
114
114
  DEFAULT_DISCOVER_SCAN_ROOT = "orp/discovery/github"
115
115
  DEFAULT_HOSTED_BASE_URL = "https://orp.earth"
116
116
  KERNEL_SCHEMA_VERSION = "1.0.0"
117
+ FRONTIER_SCHEMA_VERSION = "1.0.0"
118
+ FRONTIER_BANDS = ("exact", "structured", "horizon")
117
119
  YOUTUBE_SOURCE_SCHEMA_VERSION = "1.0.0"
118
120
  YOUTUBE_ANDROID_CLIENT_VERSION = "20.10.38"
119
121
  YOUTUBE_ANDROID_USER_AGENT = (
@@ -2011,6 +2013,406 @@ def _ensure_dirs(repo_root: Path) -> None:
2011
2013
  _write_json(state_path, _default_state_payload())
2012
2014
 
2013
2015
 
2016
+ def _frontier_root(repo_root: Path) -> Path:
2017
+ return repo_root / "orp" / "frontier"
2018
+
2019
+
2020
+ def _frontier_paths(repo_root: Path) -> dict[str, Path]:
2021
+ root = _frontier_root(repo_root)
2022
+ return {
2023
+ "root": root,
2024
+ "state_json": root / "state.json",
2025
+ "roadmap_json": root / "roadmap.json",
2026
+ "checklist_json": root / "checklist.json",
2027
+ "stack_json": root / "version-stack.json",
2028
+ "state_md": root / "STATE.md",
2029
+ "roadmap_md": root / "ROADMAP.md",
2030
+ "checklist_md": root / "CHECKLIST.md",
2031
+ "stack_md": root / "VERSION_STACK.md",
2032
+ }
2033
+
2034
+
2035
+ def _frontier_band_rules() -> dict[str, dict[str, Any]]:
2036
+ return {
2037
+ "exact": {
2038
+ "description": "Only the live milestone should be exact.",
2039
+ "max_active_milestones": 1,
2040
+ },
2041
+ "structured": {
2042
+ "description": "The next 2-3 milestones or versions should be specifically structured but still revisable.",
2043
+ },
2044
+ "horizon": {
2045
+ "description": "Farther milestones keep intent exact while phase detail stays light.",
2046
+ },
2047
+ }
2048
+
2049
+
2050
+ def _default_frontier_state_payload() -> dict[str, Any]:
2051
+ return {
2052
+ "schema_version": FRONTIER_SCHEMA_VERSION,
2053
+ "kind": "orp_frontier_state",
2054
+ "active_version": "",
2055
+ "active_milestone": "",
2056
+ "active_phase": "",
2057
+ "band": "",
2058
+ "next_action": "",
2059
+ "blocked_by": [],
2060
+ }
2061
+
2062
+
2063
+ def _default_frontier_stack_payload(program_id: str, label: str) -> dict[str, Any]:
2064
+ return {
2065
+ "schema_version": FRONTIER_SCHEMA_VERSION,
2066
+ "kind": "orp_frontier_version_stack",
2067
+ "program_id": str(program_id).strip(),
2068
+ "label": str(label).strip(),
2069
+ "band_rules": _frontier_band_rules(),
2070
+ "current_frontier": {
2071
+ "active_version": "",
2072
+ "active_milestone": "",
2073
+ "active_phase": "",
2074
+ "band": "",
2075
+ "next_action": "",
2076
+ "blocked_by": [],
2077
+ },
2078
+ "versions": [],
2079
+ }
2080
+
2081
+
2082
+ def _frontier_load_stack(repo_root: Path) -> dict[str, Any]:
2083
+ payload = _read_json_if_exists(_frontier_paths(repo_root)["stack_json"])
2084
+ if not payload:
2085
+ raise RuntimeError("frontier stack is missing. Run `orp frontier init` first.")
2086
+ return payload
2087
+
2088
+
2089
+ def _frontier_load_state(repo_root: Path) -> dict[str, Any]:
2090
+ payload = _read_json_if_exists(_frontier_paths(repo_root)["state_json"])
2091
+ if not payload:
2092
+ raise RuntimeError("frontier state is missing. Run `orp frontier init` first.")
2093
+ return payload
2094
+
2095
+
2096
+ def _frontier_find_version(stack: dict[str, Any], version_id: str) -> dict[str, Any] | None:
2097
+ versions = stack.get("versions")
2098
+ if not isinstance(versions, list):
2099
+ return None
2100
+ for version in versions:
2101
+ if isinstance(version, dict) and str(version.get("id", "")).strip() == version_id:
2102
+ return version
2103
+ return None
2104
+
2105
+
2106
+ def _frontier_find_milestone(stack: dict[str, Any], milestone_id: str) -> tuple[dict[str, Any] | None, dict[str, Any] | None]:
2107
+ versions = stack.get("versions")
2108
+ if not isinstance(versions, list):
2109
+ return (None, None)
2110
+ for version in versions:
2111
+ if not isinstance(version, dict):
2112
+ continue
2113
+ milestones = version.get("milestones")
2114
+ if not isinstance(milestones, list):
2115
+ continue
2116
+ for milestone in milestones:
2117
+ if isinstance(milestone, dict) and str(milestone.get("id", "")).strip() == milestone_id:
2118
+ return (version, milestone)
2119
+ return (None, None)
2120
+
2121
+
2122
+ def _frontier_find_phase(
2123
+ milestone: dict[str, Any],
2124
+ phase_id: str,
2125
+ ) -> dict[str, Any] | None:
2126
+ phases = milestone.get("phases")
2127
+ if not isinstance(phases, list):
2128
+ return None
2129
+ for phase in phases:
2130
+ if isinstance(phase, dict) and str(phase.get("id", "")).strip() == phase_id:
2131
+ return phase
2132
+ return None
2133
+
2134
+
2135
+ def _frontier_set_current_frontier(stack: dict[str, Any], state: dict[str, Any]) -> None:
2136
+ stack["current_frontier"] = {
2137
+ "active_version": str(state.get("active_version", "")).strip(),
2138
+ "active_milestone": str(state.get("active_milestone", "")).strip(),
2139
+ "active_phase": str(state.get("active_phase", "")).strip(),
2140
+ "band": str(state.get("band", "")).strip(),
2141
+ "next_action": str(state.get("next_action", "")).strip(),
2142
+ "blocked_by": _coerce_string_list(state.get("blocked_by")),
2143
+ }
2144
+
2145
+
2146
+ def _frontier_build_roadmap_payload(stack: dict[str, Any], state: dict[str, Any]) -> dict[str, Any]:
2147
+ active_version = str(state.get("active_version", "")).strip()
2148
+ active_milestone = str(state.get("active_milestone", "")).strip()
2149
+ version = _frontier_find_version(stack, active_version) if active_version else None
2150
+ _, milestone = _frontier_find_milestone(stack, active_milestone) if active_milestone else (None, None)
2151
+ phases = []
2152
+ if isinstance(milestone, dict):
2153
+ for phase in milestone.get("phases", []) if isinstance(milestone.get("phases"), list) else []:
2154
+ if not isinstance(phase, dict):
2155
+ continue
2156
+ phases.append(
2157
+ {
2158
+ "id": str(phase.get("id", "")).strip(),
2159
+ "label": str(phase.get("label", "")).strip(),
2160
+ "status": str(phase.get("status", "")).strip() or "planned",
2161
+ "goal": str(phase.get("goal", "")).strip(),
2162
+ "compute_hooks": list(phase.get("compute_hooks", [])) if isinstance(phase.get("compute_hooks"), list) else [],
2163
+ }
2164
+ )
2165
+ return {
2166
+ "schema_version": FRONTIER_SCHEMA_VERSION,
2167
+ "kind": "orp_frontier_roadmap",
2168
+ "program_id": str(stack.get("program_id", "")).strip(),
2169
+ "label": str(stack.get("label", "")).strip(),
2170
+ "active_version": active_version,
2171
+ "active_version_label": str(version.get("label", "")).strip() if isinstance(version, dict) else "",
2172
+ "active_milestone": active_milestone,
2173
+ "active_milestone_label": str(milestone.get("label", "")).strip() if isinstance(milestone, dict) else "",
2174
+ "band": str(state.get("band", "")).strip(),
2175
+ "next_action": str(state.get("next_action", "")).strip(),
2176
+ "phases": phases,
2177
+ }
2178
+
2179
+
2180
+ def _frontier_build_checklist_payload(stack: dict[str, Any], state: dict[str, Any]) -> dict[str, Any]:
2181
+ grouped: dict[str, list[dict[str, Any]]] = {band: [] for band in FRONTIER_BANDS}
2182
+ versions = stack.get("versions")
2183
+ if isinstance(versions, list):
2184
+ for version in versions:
2185
+ if not isinstance(version, dict):
2186
+ continue
2187
+ milestones = version.get("milestones")
2188
+ if not isinstance(milestones, list):
2189
+ continue
2190
+ for milestone in milestones:
2191
+ if not isinstance(milestone, dict):
2192
+ continue
2193
+ band = str(milestone.get("band", "")).strip() or "structured"
2194
+ if band not in grouped:
2195
+ grouped[band] = []
2196
+ phases = milestone.get("phases")
2197
+ phase_ids = []
2198
+ if isinstance(phases, list):
2199
+ phase_ids = [
2200
+ str(phase.get("id", "")).strip()
2201
+ for phase in phases
2202
+ if isinstance(phase, dict) and str(phase.get("id", "")).strip()
2203
+ ]
2204
+ grouped[band].append(
2205
+ {
2206
+ "version_id": str(version.get("id", "")).strip(),
2207
+ "version_label": str(version.get("label", "")).strip(),
2208
+ "milestone_id": str(milestone.get("id", "")).strip(),
2209
+ "milestone_label": str(milestone.get("label", "")).strip(),
2210
+ "band": band,
2211
+ "status": str(milestone.get("status", "")).strip() or "planned",
2212
+ "phase_ids": phase_ids,
2213
+ "is_active": str(milestone.get("id", "")).strip() == str(state.get("active_milestone", "")).strip(),
2214
+ }
2215
+ )
2216
+ return {
2217
+ "schema_version": FRONTIER_SCHEMA_VERSION,
2218
+ "kind": "orp_frontier_checklist",
2219
+ "program_id": str(stack.get("program_id", "")).strip(),
2220
+ "label": str(stack.get("label", "")).strip(),
2221
+ "active_version": str(state.get("active_version", "")).strip(),
2222
+ "active_milestone": str(state.get("active_milestone", "")).strip(),
2223
+ "exact": grouped.get("exact", []),
2224
+ "structured": grouped.get("structured", []),
2225
+ "horizon": grouped.get("horizon", []),
2226
+ }
2227
+
2228
+
2229
+ def _render_frontier_state_md(state: dict[str, Any], stack: dict[str, Any]) -> str:
2230
+ lines = [
2231
+ f"# Frontier State: {str(stack.get('label', '')).strip() or str(stack.get('program_id', '')).strip()}",
2232
+ "",
2233
+ f"- active_version: `{str(state.get('active_version', '')).strip() or '(unset)'}`",
2234
+ f"- active_milestone: `{str(state.get('active_milestone', '')).strip() or '(unset)'}`",
2235
+ f"- active_phase: `{str(state.get('active_phase', '')).strip() or '(unset)'}`",
2236
+ f"- band: `{str(state.get('band', '')).strip() or '(unset)'}`",
2237
+ f"- next_action: `{str(state.get('next_action', '')).strip() or '(unset)'}`",
2238
+ ]
2239
+ blockers = _coerce_string_list(state.get("blocked_by"))
2240
+ lines.append("- blocked_by:")
2241
+ if blockers:
2242
+ lines.extend([f" - `{item}`" for item in blockers])
2243
+ else:
2244
+ lines.append(" - `(none)`")
2245
+ lines.append("")
2246
+ return "\n".join(lines)
2247
+
2248
+
2249
+ def _render_frontier_roadmap_md(payload: dict[str, Any]) -> str:
2250
+ lines = [
2251
+ f"# Roadmap: {payload.get('active_milestone_label') or payload.get('active_milestone') or 'Frontier milestone not set'}",
2252
+ "",
2253
+ f"- active_version: `{payload.get('active_version', '') or '(unset)'}`",
2254
+ f"- active_milestone: `{payload.get('active_milestone', '') or '(unset)'}`",
2255
+ f"- band: `{payload.get('band', '') or '(unset)'}`",
2256
+ f"- next_action: `{payload.get('next_action', '') or '(unset)'}`",
2257
+ "",
2258
+ "## Phases",
2259
+ "",
2260
+ ]
2261
+ phases = payload.get("phases", [])
2262
+ if isinstance(phases, list) and phases:
2263
+ for phase in phases:
2264
+ if not isinstance(phase, dict):
2265
+ continue
2266
+ lines.append(
2267
+ f"- [ ] **Phase {phase.get('id', '')}: {phase.get('label', '')}** - {phase.get('goal', '') or 'goal not yet specified'}"
2268
+ )
2269
+ else:
2270
+ lines.append("- `(no active milestone phases yet)`")
2271
+ lines.append("")
2272
+ return "\n".join(lines)
2273
+
2274
+
2275
+ def _render_frontier_checklist_md(payload: dict[str, Any]) -> str:
2276
+ lines = [
2277
+ f"# Frontier Checklist: {payload.get('label', '') or payload.get('program_id', '')}",
2278
+ "",
2279
+ ]
2280
+ for band in FRONTIER_BANDS:
2281
+ rows = payload.get(band, [])
2282
+ lines.append(f"## {band.title()}")
2283
+ lines.append("")
2284
+ if isinstance(rows, list) and rows:
2285
+ for row in rows:
2286
+ if not isinstance(row, dict):
2287
+ continue
2288
+ active = " active" if row.get("is_active") else ""
2289
+ lines.append(
2290
+ f"- [ ] `{row.get('milestone_id', '')}` {row.get('milestone_label', '')} (`{row.get('version_id', '')}` / `{row.get('status', '')}`{active})"
2291
+ )
2292
+ else:
2293
+ lines.append("- `(none)`")
2294
+ lines.append("")
2295
+ return "\n".join(lines)
2296
+
2297
+
2298
+ def _render_frontier_stack_md(stack: dict[str, Any]) -> str:
2299
+ lines = [
2300
+ f"# Version Stack: {str(stack.get('label', '')).strip() or str(stack.get('program_id', '')).strip()}",
2301
+ "",
2302
+ ]
2303
+ versions = stack.get("versions")
2304
+ if isinstance(versions, list) and versions:
2305
+ for version in versions:
2306
+ if not isinstance(version, dict):
2307
+ continue
2308
+ lines.append(f"## `{version.get('id', '')}` {version.get('label', '')}")
2309
+ lines.append("")
2310
+ lines.append(f"- status: `{version.get('status', '') or 'planned'}`")
2311
+ intent = str(version.get("intent", "")).strip()
2312
+ if intent:
2313
+ lines.append(f"- intent: `{intent}`")
2314
+ milestones = version.get("milestones")
2315
+ lines.append("- milestones:")
2316
+ if isinstance(milestones, list) and milestones:
2317
+ for milestone in milestones:
2318
+ if not isinstance(milestone, dict):
2319
+ continue
2320
+ lines.append(
2321
+ f" - `{milestone.get('id', '')}` {milestone.get('label', '')} (`{milestone.get('band', '')}` / `{milestone.get('status', '') or 'planned'}`)"
2322
+ )
2323
+ else:
2324
+ lines.append(" - `(none)`")
2325
+ lines.append("")
2326
+ else:
2327
+ lines.append("- `(no versions yet)`")
2328
+ lines.append("")
2329
+ return "\n".join(lines)
2330
+
2331
+
2332
+ def _frontier_write_materialized_views(repo_root: Path, stack: dict[str, Any], state: dict[str, Any]) -> dict[str, str]:
2333
+ paths = _frontier_paths(repo_root)
2334
+ paths["root"].mkdir(parents=True, exist_ok=True)
2335
+ _frontier_set_current_frontier(stack, state)
2336
+ roadmap = _frontier_build_roadmap_payload(stack, state)
2337
+ checklist = _frontier_build_checklist_payload(stack, state)
2338
+ _write_json(paths["state_json"], state)
2339
+ _write_json(paths["stack_json"], stack)
2340
+ _write_json(paths["roadmap_json"], roadmap)
2341
+ _write_json(paths["checklist_json"], checklist)
2342
+ _write_text(paths["state_md"], _render_frontier_state_md(state, stack) + "\n")
2343
+ _write_text(paths["roadmap_md"], _render_frontier_roadmap_md(roadmap) + "\n")
2344
+ _write_text(paths["checklist_md"], _render_frontier_checklist_md(checklist) + "\n")
2345
+ _write_text(paths["stack_md"], _render_frontier_stack_md(stack) + "\n")
2346
+ return {key: _path_for_state(value, repo_root) for key, value in paths.items() if key != "root"}
2347
+
2348
+
2349
+ def _frontier_default_label(repo_root: Path, program_id: str) -> str:
2350
+ clean = str(program_id).strip()
2351
+ if clean:
2352
+ return clean.replace("-", " ").replace("_", " ").title()
2353
+ return f"{repo_root.name or 'Repo'} Frontier"
2354
+
2355
+
2356
+ def _frontier_doctor_payload(repo_root: Path) -> dict[str, Any]:
2357
+ issues: list[dict[str, Any]] = []
2358
+ paths = _frontier_paths(repo_root)
2359
+ stack = _read_json_if_exists(paths["stack_json"])
2360
+ state = _read_json_if_exists(paths["state_json"])
2361
+
2362
+ if not stack:
2363
+ issues.append({"severity": "error", "code": "missing_stack", "message": "frontier version stack is missing."})
2364
+ if not state:
2365
+ issues.append({"severity": "error", "code": "missing_state", "message": "frontier state is missing."})
2366
+
2367
+ if stack and state:
2368
+ active_version = str(state.get("active_version", "")).strip()
2369
+ active_milestone = str(state.get("active_milestone", "")).strip()
2370
+ active_phase = str(state.get("active_phase", "")).strip()
2371
+ version = _frontier_find_version(stack, active_version) if active_version else None
2372
+ _, milestone = _frontier_find_milestone(stack, active_milestone) if active_milestone else (None, None)
2373
+ if active_version and version is None:
2374
+ issues.append(
2375
+ {"severity": "error", "code": "missing_active_version", "message": f"active version `{active_version}` does not exist in version stack."}
2376
+ )
2377
+ if active_milestone and milestone is None:
2378
+ issues.append(
2379
+ {"severity": "error", "code": "missing_active_milestone", "message": f"active milestone `{active_milestone}` does not exist in version stack."}
2380
+ )
2381
+ if active_phase and isinstance(milestone, dict) and _frontier_find_phase(milestone, active_phase) is None:
2382
+ issues.append(
2383
+ {"severity": "error", "code": "missing_active_phase", "message": f"active phase `{active_phase}` does not exist in active milestone `{active_milestone}`."}
2384
+ )
2385
+ versions = stack.get("versions")
2386
+ if isinstance(versions, list):
2387
+ exact_milestones = 0
2388
+ for version_row in versions:
2389
+ if not isinstance(version_row, dict):
2390
+ continue
2391
+ milestones = version_row.get("milestones")
2392
+ if not isinstance(milestones, list):
2393
+ continue
2394
+ for milestone_row in milestones:
2395
+ if not isinstance(milestone_row, dict):
2396
+ continue
2397
+ band = str(milestone_row.get("band", "")).strip()
2398
+ if band and band not in FRONTIER_BANDS:
2399
+ issues.append(
2400
+ {"severity": "error", "code": "invalid_band", "message": f"milestone `{milestone_row.get('id', '')}` uses unsupported band `{band}`."}
2401
+ )
2402
+ if band == "exact":
2403
+ exact_milestones += 1
2404
+ if exact_milestones > 1:
2405
+ issues.append(
2406
+ {"severity": "warning", "code": "multiple_exact_milestones", "message": f"{exact_milestones} milestones are marked exact; the planning rule expects only one live exact milestone."}
2407
+ )
2408
+
2409
+ return {
2410
+ "ok": not any(issue["severity"] == "error" for issue in issues),
2411
+ "issues": issues,
2412
+ "paths": {key: _path_for_state(value, repo_root) for key, value in paths.items()},
2413
+ }
2414
+
2415
+
2014
2416
  def _write_text_if_missing(path: Path, text: str) -> str:
2015
2417
  if path.exists():
2016
2418
  return "kept"
@@ -5871,6 +6273,23 @@ def _about_payload() -> dict[str, Any]:
5871
6273
  ["collaborate", "run"],
5872
6274
  ],
5873
6275
  },
6276
+ {
6277
+ "id": "frontier",
6278
+ "description": "Version-stack, milestone, phase, and live-frontier control for long-running agent-first research programs.",
6279
+ "entrypoints": [
6280
+ ["frontier", "init"],
6281
+ ["frontier", "state"],
6282
+ ["frontier", "roadmap"],
6283
+ ["frontier", "checklist"],
6284
+ ["frontier", "stack"],
6285
+ ["frontier", "add-version"],
6286
+ ["frontier", "add-milestone"],
6287
+ ["frontier", "add-phase"],
6288
+ ["frontier", "set-live"],
6289
+ ["frontier", "render"],
6290
+ ["frontier", "doctor"],
6291
+ ],
6292
+ },
5874
6293
  {
5875
6294
  "id": "governance",
5876
6295
  "description": "Local-first repo governance, branch safety, checkpoint commits, backup refs, and runtime status.",
@@ -5960,6 +6379,17 @@ def _about_payload() -> dict[str, Any]:
5960
6379
  {"name": "collaborate_run", "path": ["collaborate", "run"], "json_output": True},
5961
6380
  {"name": "init", "path": ["init"], "json_output": True},
5962
6381
  {"name": "status", "path": ["status"], "json_output": True},
6382
+ {"name": "frontier_init", "path": ["frontier", "init"], "json_output": True},
6383
+ {"name": "frontier_state", "path": ["frontier", "state"], "json_output": True},
6384
+ {"name": "frontier_roadmap", "path": ["frontier", "roadmap"], "json_output": True},
6385
+ {"name": "frontier_checklist", "path": ["frontier", "checklist"], "json_output": True},
6386
+ {"name": "frontier_stack", "path": ["frontier", "stack"], "json_output": True},
6387
+ {"name": "frontier_add_version", "path": ["frontier", "add-version"], "json_output": True},
6388
+ {"name": "frontier_add_milestone", "path": ["frontier", "add-milestone"], "json_output": True},
6389
+ {"name": "frontier_add_phase", "path": ["frontier", "add-phase"], "json_output": True},
6390
+ {"name": "frontier_set_live", "path": ["frontier", "set-live"], "json_output": True},
6391
+ {"name": "frontier_render", "path": ["frontier", "render"], "json_output": True},
6392
+ {"name": "frontier_doctor", "path": ["frontier", "doctor"], "json_output": True},
5963
6393
  {"name": "branch_start", "path": ["branch", "start"], "json_output": True},
5964
6394
  {"name": "checkpoint_create", "path": ["checkpoint", "create"], "json_output": True},
5965
6395
  {"name": "backup", "path": ["backup"], "json_output": True},
@@ -5983,6 +6413,7 @@ def _about_payload() -> dict[str, Any]:
5983
6413
  "YouTube inspection is a built-in ORP ability exposed through `orp youtube inspect`, returning public metadata plus full transcript text and segments whenever public caption tracks are available.",
5984
6414
  "Discovery profiles in ORP are portable search-intent files managed directly by ORP.",
5985
6415
  "Collaboration is a built-in ORP ability exposed through `orp collaborate ...`.",
6416
+ "Frontier control is a built-in ORP ability exposed through `orp frontier ...`, separating the exact live point, the exact active milestone, the near structured checklist, and the farther major-version stack.",
5986
6417
  "Project/session linking is a built-in ORP ability exposed through `orp link ...` and stored machine-locally under `.git/orp/link/`.",
5987
6418
  "Machine runner identity, heartbeat, hosted sync, prompt-job execution, and lease control are built into ORP through `orp runner status`, `orp runner enable`, `orp runner disable`, `orp runner heartbeat`, `orp runner sync`, `orp runner work`, `orp runner cancel`, and `orp runner retry`.",
5988
6419
  "Repo governance is built into ORP through `orp init`, `orp status`, `orp branch start`, `orp checkpoint create`, `orp backup`, `orp ready`, `orp doctor`, and `orp cleanup`.",
@@ -6082,6 +6513,10 @@ def _home_payload(repo_root: Path, config_arg: str) -> dict[str, Any]:
6082
6513
  runtime_initialized = state_exists or (repo_root / "orp").exists()
6083
6514
 
6084
6515
  quick_actions = [
6516
+ {
6517
+ "label": "Initialize a frontier version stack for this repo",
6518
+ "command": "orp frontier init --program-id <program-id> --json",
6519
+ },
6085
6520
  {
6086
6521
  "label": "Connect ORP to the hosted workspace",
6087
6522
  "command": "orp auth login",
@@ -6188,34 +6623,48 @@ def _home_payload(repo_root: Path, config_arg: str) -> dict[str, Any]:
6188
6623
  )
6189
6624
  quick_actions.insert(
6190
6625
  6,
6626
+ {
6627
+ "label": "Inspect the exact live frontier point",
6628
+ "command": "orp frontier state --json",
6629
+ },
6630
+ )
6631
+ quick_actions.insert(
6632
+ 7,
6633
+ {
6634
+ "label": "Inspect the active milestone roadmap",
6635
+ "command": "orp frontier roadmap --json",
6636
+ },
6637
+ )
6638
+ quick_actions.insert(
6639
+ 8,
6191
6640
  {
6192
6641
  "label": "Mark the repo locally ready after validation",
6193
6642
  "command": "orp ready --json",
6194
6643
  },
6195
6644
  )
6196
6645
  quick_actions.insert(
6197
- 7,
6646
+ 9,
6198
6647
  {
6199
6648
  "label": "Inspect local project/session link state",
6200
6649
  "command": "orp link status --json",
6201
6650
  },
6202
6651
  )
6203
6652
  quick_actions.insert(
6204
- 7,
6653
+ 9,
6205
6654
  {
6206
6655
  "label": "Inspect machine runner state",
6207
6656
  "command": "orp runner status --json",
6208
6657
  },
6209
6658
  )
6210
6659
  quick_actions.insert(
6211
- 8,
6660
+ 10,
6212
6661
  {
6213
6662
  "label": "Inspect and repair governance health",
6214
6663
  "command": "orp doctor --json",
6215
6664
  },
6216
6665
  )
6217
6666
  quick_actions.insert(
6218
- 9,
6667
+ 11,
6219
6668
  {
6220
6669
  "label": "Inspect safe cleanup candidates",
6221
6670
  "command": "orp cleanup --json",
@@ -6305,6 +6754,17 @@ def _home_payload(repo_root: Path, config_arg: str) -> dict[str, Any]:
6305
6754
  "orp collaborate run --workflow full_flow --json",
6306
6755
  ],
6307
6756
  },
6757
+ {
6758
+ "id": "frontier",
6759
+ "description": "Version-stack, milestone, phase, and exact live-frontier control for long-running agent-first research programs.",
6760
+ "entrypoints": [
6761
+ "orp frontier init --program-id <program-id> --json",
6762
+ "orp frontier state --json",
6763
+ "orp frontier roadmap --json",
6764
+ "orp frontier checklist --json",
6765
+ "orp frontier stack --json",
6766
+ ],
6767
+ },
6308
6768
  {
6309
6769
  "id": "governance",
6310
6770
  "description": "Local-first repo governance, branch safety, checkpoint commits, backup refs, and runtime status.",
@@ -7913,6 +8373,342 @@ def cmd_cleanup(args: argparse.Namespace) -> int:
7913
8373
  return 0
7914
8374
 
7915
8375
 
8376
+ def cmd_frontier_init(args: argparse.Namespace) -> int:
8377
+ repo_root = Path(args.repo_root).resolve()
8378
+ _ensure_dirs(repo_root)
8379
+ paths = _frontier_paths(repo_root)
8380
+ if paths["stack_json"].exists() and not args.force:
8381
+ raise RuntimeError(
8382
+ f"frontier already exists at {_path_for_state(paths['stack_json'], repo_root)}. Use --force to overwrite."
8383
+ )
8384
+
8385
+ program_id = str(args.program_id or "").strip() or (repo_root.name or "research-program")
8386
+ label = str(args.label or "").strip() or _frontier_default_label(repo_root, program_id)
8387
+ stack = _default_frontier_stack_payload(program_id, label)
8388
+ state = _default_frontier_state_payload()
8389
+ written = _frontier_write_materialized_views(repo_root, stack, state)
8390
+ result = {
8391
+ "ok": True,
8392
+ "program_id": program_id,
8393
+ "label": label,
8394
+ "paths": written,
8395
+ }
8396
+ if args.json_output:
8397
+ _print_json(result)
8398
+ else:
8399
+ print(f"program_id={program_id}")
8400
+ print(f"label={label}")
8401
+ for key, value in written.items():
8402
+ print(f"{key}={value}")
8403
+ return 0
8404
+
8405
+
8406
+ def cmd_frontier_state(args: argparse.Namespace) -> int:
8407
+ repo_root = Path(args.repo_root).resolve()
8408
+ stack = _frontier_load_stack(repo_root)
8409
+ state = _frontier_load_state(repo_root)
8410
+ payload = {
8411
+ **state,
8412
+ "program_id": str(stack.get("program_id", "")).strip(),
8413
+ "label": str(stack.get("label", "")).strip(),
8414
+ "paths": {
8415
+ "state_json": _path_for_state(_frontier_paths(repo_root)["state_json"], repo_root),
8416
+ "state_md": _path_for_state(_frontier_paths(repo_root)["state_md"], repo_root),
8417
+ },
8418
+ }
8419
+ if args.json_output:
8420
+ _print_json(payload)
8421
+ else:
8422
+ print(f"program_id={payload['program_id']}")
8423
+ print(f"active_version={payload.get('active_version', '')}")
8424
+ print(f"active_milestone={payload.get('active_milestone', '')}")
8425
+ print(f"active_phase={payload.get('active_phase', '')}")
8426
+ print(f"band={payload.get('band', '')}")
8427
+ print(f"next_action={payload.get('next_action', '')}")
8428
+ blockers = _coerce_string_list(payload.get("blocked_by"))
8429
+ print("blocked_by=" + (",".join(blockers) if blockers else "(none)"))
8430
+ return 0
8431
+
8432
+
8433
+ def cmd_frontier_stack(args: argparse.Namespace) -> int:
8434
+ repo_root = Path(args.repo_root).resolve()
8435
+ stack = _frontier_load_stack(repo_root)
8436
+ payload = {
8437
+ **stack,
8438
+ "paths": {
8439
+ "stack_json": _path_for_state(_frontier_paths(repo_root)["stack_json"], repo_root),
8440
+ "stack_md": _path_for_state(_frontier_paths(repo_root)["stack_md"], repo_root),
8441
+ },
8442
+ }
8443
+ if args.json_output:
8444
+ _print_json(payload)
8445
+ else:
8446
+ print(f"program_id={payload.get('program_id', '')}")
8447
+ print(f"label={payload.get('label', '')}")
8448
+ print(f"versions={len(payload.get('versions', [])) if isinstance(payload.get('versions'), list) else 0}")
8449
+ return 0
8450
+
8451
+
8452
+ def cmd_frontier_roadmap(args: argparse.Namespace) -> int:
8453
+ repo_root = Path(args.repo_root).resolve()
8454
+ payload = _read_json_if_exists(_frontier_paths(repo_root)["roadmap_json"])
8455
+ if not payload:
8456
+ stack = _frontier_load_stack(repo_root)
8457
+ state = _frontier_load_state(repo_root)
8458
+ payload = _frontier_build_roadmap_payload(stack, state)
8459
+ if args.json_output:
8460
+ _print_json(payload)
8461
+ else:
8462
+ print(f"active_version={payload.get('active_version', '')}")
8463
+ print(f"active_milestone={payload.get('active_milestone', '')}")
8464
+ print(f"phases={len(payload.get('phases', [])) if isinstance(payload.get('phases'), list) else 0}")
8465
+ return 0
8466
+
8467
+
8468
+ def cmd_frontier_checklist(args: argparse.Namespace) -> int:
8469
+ repo_root = Path(args.repo_root).resolve()
8470
+ payload = _read_json_if_exists(_frontier_paths(repo_root)["checklist_json"])
8471
+ if not payload:
8472
+ stack = _frontier_load_stack(repo_root)
8473
+ state = _frontier_load_state(repo_root)
8474
+ payload = _frontier_build_checklist_payload(stack, state)
8475
+ if args.json_output:
8476
+ _print_json(payload)
8477
+ else:
8478
+ print(f"active_version={payload.get('active_version', '')}")
8479
+ print(f"active_milestone={payload.get('active_milestone', '')}")
8480
+ print(f"exact={len(payload.get('exact', [])) if isinstance(payload.get('exact'), list) else 0}")
8481
+ print(f"structured={len(payload.get('structured', [])) if isinstance(payload.get('structured'), list) else 0}")
8482
+ print(f"horizon={len(payload.get('horizon', [])) if isinstance(payload.get('horizon'), list) else 0}")
8483
+ return 0
8484
+
8485
+
8486
+ def cmd_frontier_add_version(args: argparse.Namespace) -> int:
8487
+ repo_root = Path(args.repo_root).resolve()
8488
+ stack = _frontier_load_stack(repo_root)
8489
+ state = _frontier_load_state(repo_root)
8490
+ version_id = str(args.id).strip()
8491
+ if _frontier_find_version(stack, version_id) is not None:
8492
+ raise RuntimeError(f"frontier version `{version_id}` already exists.")
8493
+ version = {
8494
+ "id": version_id,
8495
+ "label": str(args.label).strip(),
8496
+ "intent": str(args.intent or "").strip(),
8497
+ "status": str(args.status or "planned").strip() or "planned",
8498
+ "milestones": [],
8499
+ }
8500
+ versions = stack.get("versions")
8501
+ if not isinstance(versions, list):
8502
+ versions = []
8503
+ stack["versions"] = versions
8504
+ versions.append(version)
8505
+ written = _frontier_write_materialized_views(repo_root, stack, state)
8506
+ result = {"ok": True, "version": version, "paths": written}
8507
+ if args.json_output:
8508
+ _print_json(result)
8509
+ else:
8510
+ print(f"version_id={version_id}")
8511
+ print(f"label={version['label']}")
8512
+ return 0
8513
+
8514
+
8515
+ def cmd_frontier_add_milestone(args: argparse.Namespace) -> int:
8516
+ repo_root = Path(args.repo_root).resolve()
8517
+ stack = _frontier_load_stack(repo_root)
8518
+ state = _frontier_load_state(repo_root)
8519
+ version_id = str(args.version).strip()
8520
+ version = _frontier_find_version(stack, version_id)
8521
+ if version is None:
8522
+ raise RuntimeError(f"frontier version `{version_id}` was not found.")
8523
+ milestone_id = str(args.id).strip()
8524
+ _, existing = _frontier_find_milestone(stack, milestone_id)
8525
+ if existing is not None:
8526
+ raise RuntimeError(f"frontier milestone `{milestone_id}` already exists.")
8527
+ band = str(args.band or "structured").strip()
8528
+ if band not in FRONTIER_BANDS:
8529
+ raise RuntimeError(f"frontier band must be one of: {', '.join(FRONTIER_BANDS)}")
8530
+ milestone = {
8531
+ "id": milestone_id,
8532
+ "parent_version": version_id,
8533
+ "label": str(args.label).strip(),
8534
+ "band": band,
8535
+ "status": str(args.status or "planned").strip() or "planned",
8536
+ "depends_on": _coerce_string_list(getattr(args, "depends_on", [])),
8537
+ "success_criteria": _coerce_string_list(getattr(args, "success_criterion", [])),
8538
+ "phases": [],
8539
+ }
8540
+ milestones = version.get("milestones")
8541
+ if not isinstance(milestones, list):
8542
+ milestones = []
8543
+ version["milestones"] = milestones
8544
+ milestones.append(milestone)
8545
+ written = _frontier_write_materialized_views(repo_root, stack, state)
8546
+ result = {"ok": True, "milestone": milestone, "paths": written}
8547
+ if args.json_output:
8548
+ _print_json(result)
8549
+ else:
8550
+ print(f"milestone_id={milestone_id}")
8551
+ print(f"version_id={version_id}")
8552
+ return 0
8553
+
8554
+
8555
+ def cmd_frontier_add_phase(args: argparse.Namespace) -> int:
8556
+ repo_root = Path(args.repo_root).resolve()
8557
+ stack = _frontier_load_stack(repo_root)
8558
+ state = _frontier_load_state(repo_root)
8559
+ milestone_id = str(args.milestone).strip()
8560
+ _, milestone = _frontier_find_milestone(stack, milestone_id)
8561
+ if milestone is None:
8562
+ raise RuntimeError(f"frontier milestone `{milestone_id}` was not found.")
8563
+ phase_id = str(args.id).strip()
8564
+ if _frontier_find_phase(milestone, phase_id) is not None:
8565
+ raise RuntimeError(f"frontier phase `{phase_id}` already exists in milestone `{milestone_id}`.")
8566
+ compute_hooks: list[dict[str, Any]] = []
8567
+ compute_point_id = str(getattr(args, "compute_point_id", "") or "").strip()
8568
+ if compute_point_id:
8569
+ compute_hooks.append(
8570
+ {
8571
+ "compute_point_id": compute_point_id,
8572
+ "allowed_rungs": _coerce_string_list(getattr(args, "allowed_rung", [])),
8573
+ "paid_requires_user_approval": bool(getattr(args, "paid_requires_user_approval", False)),
8574
+ }
8575
+ )
8576
+ phase = {
8577
+ "id": phase_id,
8578
+ "label": str(args.label).strip(),
8579
+ "status": str(args.status or "planned").strip() or "planned",
8580
+ "goal": str(args.goal or "").strip(),
8581
+ "depends_on": _coerce_string_list(getattr(args, "depends_on", [])),
8582
+ "requirements": _coerce_string_list(getattr(args, "requirement", [])),
8583
+ "success_criteria": _coerce_string_list(getattr(args, "success_criterion", [])),
8584
+ "plans": _coerce_string_list(getattr(args, "plan", [])),
8585
+ "compute_hooks": compute_hooks,
8586
+ }
8587
+ phases = milestone.get("phases")
8588
+ if not isinstance(phases, list):
8589
+ phases = []
8590
+ milestone["phases"] = phases
8591
+ phases.append(phase)
8592
+ written = _frontier_write_materialized_views(repo_root, stack, state)
8593
+ result = {"ok": True, "phase": phase, "paths": written}
8594
+ if args.json_output:
8595
+ _print_json(result)
8596
+ else:
8597
+ print(f"phase_id={phase_id}")
8598
+ print(f"milestone_id={milestone_id}")
8599
+ return 0
8600
+
8601
+
8602
+ def cmd_frontier_set_live(args: argparse.Namespace) -> int:
8603
+ repo_root = Path(args.repo_root).resolve()
8604
+ stack = _frontier_load_stack(repo_root)
8605
+ state = _frontier_load_state(repo_root)
8606
+ version_id = str(args.version).strip()
8607
+ milestone_id = str(args.milestone).strip()
8608
+ phase_id = str(args.phase or "").strip()
8609
+
8610
+ version = _frontier_find_version(stack, version_id)
8611
+ if version is None:
8612
+ raise RuntimeError(f"frontier version `{version_id}` was not found.")
8613
+ _, milestone = _frontier_find_milestone(stack, milestone_id)
8614
+ if milestone is None:
8615
+ raise RuntimeError(f"frontier milestone `{milestone_id}` was not found.")
8616
+ if str(milestone.get("parent_version", "")).strip() and str(milestone.get("parent_version", "")).strip() != version_id:
8617
+ raise RuntimeError(f"frontier milestone `{milestone_id}` does not belong to version `{version_id}`.")
8618
+ if phase_id and _frontier_find_phase(milestone, phase_id) is None:
8619
+ raise RuntimeError(f"frontier phase `{phase_id}` was not found in milestone `{milestone_id}`.")
8620
+
8621
+ versions = stack.get("versions")
8622
+ if isinstance(versions, list):
8623
+ for version_row in versions:
8624
+ if not isinstance(version_row, dict):
8625
+ continue
8626
+ version_row["status"] = "active" if str(version_row.get("id", "")).strip() == version_id else (
8627
+ str(version_row.get("status", "")).strip() or "planned"
8628
+ )
8629
+ milestones = version_row.get("milestones")
8630
+ if not isinstance(milestones, list):
8631
+ continue
8632
+ for milestone_row in milestones:
8633
+ if not isinstance(milestone_row, dict):
8634
+ continue
8635
+ if str(milestone_row.get("id", "")).strip() == milestone_id:
8636
+ milestone_row["status"] = "active"
8637
+ elif str(milestone_row.get("status", "")).strip() == "active":
8638
+ milestone_row["status"] = "planned"
8639
+ phases = milestone_row.get("phases")
8640
+ if not isinstance(phases, list):
8641
+ continue
8642
+ for phase_row in phases:
8643
+ if not isinstance(phase_row, dict):
8644
+ continue
8645
+ if phase_id and str(milestone_row.get("id", "")).strip() == milestone_id:
8646
+ if str(phase_row.get("id", "")).strip() == phase_id:
8647
+ phase_row["status"] = "active"
8648
+ elif str(phase_row.get("status", "")).strip() == "active":
8649
+ phase_row["status"] = "planned"
8650
+
8651
+ band = str(args.band or milestone.get("band", "") or "").strip()
8652
+ if band and band not in FRONTIER_BANDS:
8653
+ raise RuntimeError(f"frontier band must be one of: {', '.join(FRONTIER_BANDS)}")
8654
+ state["active_version"] = version_id
8655
+ state["active_milestone"] = milestone_id
8656
+ state["active_phase"] = phase_id
8657
+ state["band"] = band
8658
+ next_action = str(args.next_action or "").strip()
8659
+ if not next_action:
8660
+ next_action = f"execute phase {phase_id}" if phase_id else f"execute milestone {milestone_id}"
8661
+ state["next_action"] = next_action
8662
+ state["blocked_by"] = _coerce_string_list(getattr(args, "blocked_by", []))
8663
+
8664
+ written = _frontier_write_materialized_views(repo_root, stack, state)
8665
+ result = {"ok": True, "state": state, "paths": written}
8666
+ if args.json_output:
8667
+ _print_json(result)
8668
+ else:
8669
+ print(f"active_version={state['active_version']}")
8670
+ print(f"active_milestone={state['active_milestone']}")
8671
+ print(f"active_phase={state['active_phase']}")
8672
+ print(f"next_action={state['next_action']}")
8673
+ return 0
8674
+
8675
+
8676
+ def cmd_frontier_render(args: argparse.Namespace) -> int:
8677
+ repo_root = Path(args.repo_root).resolve()
8678
+ stack = _frontier_load_stack(repo_root)
8679
+ state = _frontier_load_state(repo_root)
8680
+ written = _frontier_write_materialized_views(repo_root, stack, state)
8681
+ result = {"ok": True, "paths": written}
8682
+ if args.json_output:
8683
+ _print_json(result)
8684
+ else:
8685
+ for key, value in written.items():
8686
+ print(f"{key}={value}")
8687
+ return 0
8688
+
8689
+
8690
+ def cmd_frontier_doctor(args: argparse.Namespace) -> int:
8691
+ repo_root = Path(args.repo_root).resolve()
8692
+ payload = _frontier_doctor_payload(repo_root)
8693
+ fixes_applied: list[str] = []
8694
+ if args.fix and payload["ok"]:
8695
+ stack = _frontier_load_stack(repo_root)
8696
+ state = _frontier_load_state(repo_root)
8697
+ _frontier_write_materialized_views(repo_root, stack, state)
8698
+ fixes_applied.append("rendered_frontier_views")
8699
+ payload["fix"] = bool(args.fix)
8700
+ payload["fixes_applied"] = fixes_applied
8701
+ if args.json_output:
8702
+ _print_json(payload)
8703
+ else:
8704
+ print(f"ok={'true' if payload['ok'] else 'false'}")
8705
+ for issue in payload.get("issues", []):
8706
+ print(f"issue={issue.get('severity','')}:{issue.get('code','')}:{issue.get('message','')}")
8707
+ for fix_name in fixes_applied:
8708
+ print(f"fix={fix_name}")
8709
+ return 0 if payload["ok"] else 1
8710
+
8711
+
7916
8712
  def _load_profile(config: dict[str, Any], name: str) -> dict[str, Any]:
7917
8713
  profiles = config.get("profiles")
7918
8714
  if not isinstance(profiles, dict):
@@ -13823,6 +14619,203 @@ def build_parser() -> argparse.ArgumentParser:
13823
14619
  add_json_flag(s_cleanup)
13824
14620
  s_cleanup.set_defaults(func=cmd_cleanup, json_output=False)
13825
14621
 
14622
+ s_frontier = sub.add_parser(
14623
+ "frontier",
14624
+ help="Version-stack, milestone, and phase frontier operations for agent-first research programs",
14625
+ )
14626
+ frontier_sub = s_frontier.add_subparsers(dest="frontier_cmd", required=True)
14627
+
14628
+ s_frontier_init = frontier_sub.add_parser(
14629
+ "init",
14630
+ help="Initialize the ORP frontier control surface under orp/frontier/",
14631
+ )
14632
+ s_frontier_init.add_argument("--program-id", default="", help="Frontier program id")
14633
+ s_frontier_init.add_argument("--label", default="", help="Human label for the frontier program")
14634
+ s_frontier_init.add_argument(
14635
+ "--force",
14636
+ action="store_true",
14637
+ help="Overwrite an existing frontier control surface",
14638
+ )
14639
+ add_json_flag(s_frontier_init)
14640
+ s_frontier_init.set_defaults(func=cmd_frontier_init, json_output=False)
14641
+
14642
+ s_frontier_state = frontier_sub.add_parser(
14643
+ "state",
14644
+ help="Show the exact live frontier point",
14645
+ )
14646
+ add_json_flag(s_frontier_state)
14647
+ s_frontier_state.set_defaults(func=cmd_frontier_state, json_output=False)
14648
+
14649
+ s_frontier_roadmap = frontier_sub.add_parser(
14650
+ "roadmap",
14651
+ help="Show the exact active milestone roadmap",
14652
+ )
14653
+ add_json_flag(s_frontier_roadmap)
14654
+ s_frontier_roadmap.set_defaults(func=cmd_frontier_roadmap, json_output=False)
14655
+
14656
+ s_frontier_checklist = frontier_sub.add_parser(
14657
+ "checklist",
14658
+ help="Show the near-term exact/structured/horizon checklist",
14659
+ )
14660
+ add_json_flag(s_frontier_checklist)
14661
+ s_frontier_checklist.set_defaults(func=cmd_frontier_checklist, json_output=False)
14662
+
14663
+ s_frontier_stack = frontier_sub.add_parser(
14664
+ "stack",
14665
+ help="Show the larger major-version stack",
14666
+ )
14667
+ add_json_flag(s_frontier_stack)
14668
+ s_frontier_stack.set_defaults(func=cmd_frontier_stack, json_output=False)
14669
+
14670
+ s_frontier_add_version = frontier_sub.add_parser(
14671
+ "add-version",
14672
+ help="Add one major version to the frontier stack",
14673
+ )
14674
+ s_frontier_add_version.add_argument("--id", required=True, help="Version id, for example v11")
14675
+ s_frontier_add_version.add_argument("--label", required=True, help="Version label")
14676
+ s_frontier_add_version.add_argument("--intent", default="", help="Optional version intent")
14677
+ s_frontier_add_version.add_argument(
14678
+ "--status",
14679
+ default="planned",
14680
+ choices=["planned", "active", "horizon", "complete"],
14681
+ help="Version status (default: planned)",
14682
+ )
14683
+ add_json_flag(s_frontier_add_version)
14684
+ s_frontier_add_version.set_defaults(func=cmd_frontier_add_version, json_output=False)
14685
+
14686
+ s_frontier_add_milestone = frontier_sub.add_parser(
14687
+ "add-milestone",
14688
+ help="Add one milestone under a major version",
14689
+ )
14690
+ s_frontier_add_milestone.add_argument("--version", required=True, help="Parent version id")
14691
+ s_frontier_add_milestone.add_argument("--id", required=True, help="Milestone id, for example v10.4")
14692
+ s_frontier_add_milestone.add_argument("--label", required=True, help="Milestone label")
14693
+ s_frontier_add_milestone.add_argument(
14694
+ "--band",
14695
+ default="structured",
14696
+ choices=list(FRONTIER_BANDS),
14697
+ help="Planning band (default: structured)",
14698
+ )
14699
+ s_frontier_add_milestone.add_argument(
14700
+ "--status",
14701
+ default="planned",
14702
+ choices=["planned", "active", "horizon", "complete"],
14703
+ help="Milestone status (default: planned)",
14704
+ )
14705
+ s_frontier_add_milestone.add_argument(
14706
+ "--depends-on",
14707
+ action="append",
14708
+ default=[],
14709
+ help="Dependency milestone or phase id (repeatable)",
14710
+ )
14711
+ s_frontier_add_milestone.add_argument(
14712
+ "--success-criterion",
14713
+ action="append",
14714
+ default=[],
14715
+ help="Milestone success criterion (repeatable)",
14716
+ )
14717
+ add_json_flag(s_frontier_add_milestone)
14718
+ s_frontier_add_milestone.set_defaults(func=cmd_frontier_add_milestone, json_output=False)
14719
+
14720
+ s_frontier_add_phase = frontier_sub.add_parser(
14721
+ "add-phase",
14722
+ help="Add one phase under a milestone",
14723
+ )
14724
+ s_frontier_add_phase.add_argument("--milestone", required=True, help="Parent milestone id")
14725
+ s_frontier_add_phase.add_argument("--id", required=True, help="Phase id")
14726
+ s_frontier_add_phase.add_argument("--label", required=True, help="Phase label")
14727
+ s_frontier_add_phase.add_argument(
14728
+ "--status",
14729
+ default="planned",
14730
+ choices=["planned", "active", "complete"],
14731
+ help="Phase status (default: planned)",
14732
+ )
14733
+ s_frontier_add_phase.add_argument("--goal", default="", help="Optional phase goal")
14734
+ s_frontier_add_phase.add_argument(
14735
+ "--depends-on",
14736
+ action="append",
14737
+ default=[],
14738
+ help="Dependency phase or milestone id (repeatable)",
14739
+ )
14740
+ s_frontier_add_phase.add_argument(
14741
+ "--requirement",
14742
+ action="append",
14743
+ default=[],
14744
+ help="Requirement identifier or note (repeatable)",
14745
+ )
14746
+ s_frontier_add_phase.add_argument(
14747
+ "--success-criterion",
14748
+ action="append",
14749
+ default=[],
14750
+ help="Phase success criterion (repeatable)",
14751
+ )
14752
+ s_frontier_add_phase.add_argument(
14753
+ "--plan",
14754
+ action="append",
14755
+ default=[],
14756
+ help="Plan id or plan note (repeatable)",
14757
+ )
14758
+ s_frontier_add_phase.add_argument(
14759
+ "--compute-point-id",
14760
+ default="",
14761
+ help="Optional linked compute point id",
14762
+ )
14763
+ s_frontier_add_phase.add_argument(
14764
+ "--allowed-rung",
14765
+ action="append",
14766
+ default=[],
14767
+ help="Allowed compute rung for the compute hook (repeatable)",
14768
+ )
14769
+ s_frontier_add_phase.add_argument(
14770
+ "--paid-requires-user-approval",
14771
+ action="store_true",
14772
+ help="Mark the attached compute hook as requiring explicit user approval for paid compute",
14773
+ )
14774
+ add_json_flag(s_frontier_add_phase)
14775
+ s_frontier_add_phase.set_defaults(func=cmd_frontier_add_phase, json_output=False)
14776
+
14777
+ s_frontier_set_live = frontier_sub.add_parser(
14778
+ "set-live",
14779
+ help="Update the exact live frontier pointer",
14780
+ )
14781
+ s_frontier_set_live.add_argument("--version", required=True, help="Active version id")
14782
+ s_frontier_set_live.add_argument("--milestone", required=True, help="Active milestone id")
14783
+ s_frontier_set_live.add_argument("--phase", default="", help="Active phase id")
14784
+ s_frontier_set_live.add_argument(
14785
+ "--band",
14786
+ default="",
14787
+ choices=["", *FRONTIER_BANDS],
14788
+ help="Optional explicit band override",
14789
+ )
14790
+ s_frontier_set_live.add_argument("--next-action", default="", help="Optional live next action override")
14791
+ s_frontier_set_live.add_argument(
14792
+ "--blocked-by",
14793
+ action="append",
14794
+ default=[],
14795
+ help="Current blocker id or note (repeatable)",
14796
+ )
14797
+ add_json_flag(s_frontier_set_live)
14798
+ s_frontier_set_live.set_defaults(func=cmd_frontier_set_live, json_output=False)
14799
+
14800
+ s_frontier_render = frontier_sub.add_parser(
14801
+ "render",
14802
+ help="Refresh the materialized frontier JSON and markdown views",
14803
+ )
14804
+ add_json_flag(s_frontier_render)
14805
+ s_frontier_render.set_defaults(func=cmd_frontier_render, json_output=False)
14806
+
14807
+ s_frontier_doctor = frontier_sub.add_parser(
14808
+ "doctor",
14809
+ help="Validate frontier consistency and optionally re-render views",
14810
+ )
14811
+ s_frontier_doctor.add_argument(
14812
+ "--fix",
14813
+ action="store_true",
14814
+ help="Re-render materialized frontier views when the frontier is otherwise consistent",
14815
+ )
14816
+ add_json_flag(s_frontier_doctor)
14817
+ s_frontier_doctor.set_defaults(func=cmd_frontier_doctor, json_output=False)
14818
+
13826
14819
  s_kernel = sub.add_parser("kernel", help="Reasoning-kernel artifact operations")
13827
14820
  kernel_sub = s_kernel.add_subparsers(dest="kernel_cmd", required=True)
13828
14821
 
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "open-research-protocol",
3
- "version": "0.4.12",
3
+ "version": "0.4.14",
4
4
  "description": "ORP CLI (Open Research Protocol): agent-friendly research workflows, runtime, reports, and pack tooling.",
5
5
  "license": "MIT",
6
+ "author": "Fractal Research Group <cody@frg.earth>",
6
7
  "repository": {
7
8
  "type": "git",
8
9
  "url": "git+https://github.com/SproutSeeds/orp.git"
@@ -201,9 +201,9 @@ def _benchmark_init_starter(iterations: int) -> dict[str, Any]:
201
201
  run_records.append(gate_payload["run_record"])
202
202
 
203
203
  targets = {
204
- "init_mean_lt_ms": 375.0,
205
- "validate_mean_lt_ms": 250.0,
206
- "gate_mean_lt_ms": 350.0,
204
+ "init_mean_lt_ms": 900.0,
205
+ "validate_mean_lt_ms": 700.0,
206
+ "gate_mean_lt_ms": 1000.0,
207
207
  }
208
208
  observed = {
209
209
  "init": _stats(init_times),
@@ -264,8 +264,8 @@ def _benchmark_artifact_roundtrip() -> dict[str, Any]:
264
264
  "validate": _stats(validate_times),
265
265
  }
266
266
  targets = {
267
- "scaffold_mean_lt_ms": 210.0,
268
- "validate_mean_lt_ms": 210.0,
267
+ "scaffold_mean_lt_ms": 350.0,
268
+ "validate_mean_lt_ms": 325.0,
269
269
  }
270
270
  return {
271
271
  "artifact_classes_total": len(rows),
@@ -490,7 +490,7 @@ def _benchmark_cross_domain_corpus() -> dict[str, Any]:
490
490
  targets = {
491
491
  "domains_min": 5,
492
492
  "fixtures_min": 7,
493
- "validate_mean_lt_ms": 210.0,
493
+ "validate_mean_lt_ms": 260.0,
494
494
  }
495
495
  return {
496
496
  "fixtures_total": len(rows),
@@ -549,7 +549,7 @@ def _benchmark_requirement_enforcement() -> dict[str, Any]:
549
549
  observed = {"validate": _stats(validate_times)}
550
550
  targets = {
551
551
  "all_cases_detected": sum(len(fields) for fields in requirements.values()),
552
- "validate_mean_lt_ms": 210.0,
552
+ "validate_mean_lt_ms": 275.0,
553
553
  }
554
554
  return {
555
555
  "cases_total": len(rows),
@@ -717,7 +717,7 @@ def _benchmark_mutation_stress() -> dict[str, Any]:
717
717
  observed = {"validate": _stats(validate_times)}
718
718
  targets = {
719
719
  "cases_total": len(cases),
720
- "validate_mean_lt_ms": 210.0,
720
+ "validate_mean_lt_ms": 275.0,
721
721
  }
722
722
  return {
723
723
  "cases_total": len(rows),