@researai/deepscientist 1.5.7 → 1.5.8
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 +4 -0
- package/bin/ds.js +220 -5
- package/docs/en/07_MEMORY_AND_MCP.md +40 -3
- package/docs/en/99_ACKNOWLEDGEMENTS.md +1 -0
- package/docs/zh/07_MEMORY_AND_MCP.md +40 -3
- package/docs/zh/99_ACKNOWLEDGEMENTS.md +1 -0
- package/install.sh +34 -0
- package/package.json +1 -1
- package/pyproject.toml +1 -1
- package/src/deepscientist/__init__.py +1 -1
- package/src/deepscientist/acp/envelope.py +1 -0
- package/src/deepscientist/artifact/metrics.py +813 -80
- package/src/deepscientist/artifact/schemas.py +1 -0
- package/src/deepscientist/artifact/service.py +1101 -99
- package/src/deepscientist/bash_exec/monitor.py +1 -1
- package/src/deepscientist/bash_exec/service.py +17 -9
- package/src/deepscientist/channels/qq.py +17 -0
- package/src/deepscientist/channels/relay.py +16 -0
- package/src/deepscientist/config/models.py +6 -0
- package/src/deepscientist/config/service.py +70 -2
- package/src/deepscientist/daemon/api/handlers.py +284 -14
- package/src/deepscientist/daemon/api/router.py +1 -0
- package/src/deepscientist/daemon/app.py +291 -20
- package/src/deepscientist/gitops/diff.py +6 -10
- package/src/deepscientist/mcp/server.py +188 -39
- package/src/deepscientist/prompts/builder.py +51 -18
- package/src/deepscientist/quest/service.py +83 -34
- package/src/deepscientist/quest/stage_views.py +74 -29
- package/src/deepscientist/runners/codex.py +1 -1
- package/src/prompts/connectors/qq.md +1 -1
- package/src/prompts/contracts/shared_interaction.md +14 -0
- package/src/prompts/system.md +106 -32
- package/src/skills/analysis-campaign/SKILL.md +10 -14
- package/src/skills/baseline/SKILL.md +51 -38
- package/src/skills/baseline/references/baseline-plan-template.md +2 -0
- package/src/skills/decision/SKILL.md +12 -8
- package/src/skills/experiment/SKILL.md +28 -16
- package/src/skills/experiment/references/main-experiment-plan-template.md +2 -0
- package/src/skills/figure-polish/SKILL.md +1 -0
- package/src/skills/finalize/SKILL.md +3 -8
- package/src/skills/idea/SKILL.md +2 -8
- package/src/skills/intake-audit/SKILL.md +2 -8
- package/src/skills/rebuttal/SKILL.md +2 -8
- package/src/skills/review/SKILL.md +2 -8
- package/src/skills/scout/SKILL.md +2 -8
- package/src/skills/write/SKILL.md +52 -16
- package/src/skills/write/templates/DEEPSCIENTIST_NOTES.md +21 -0
- package/src/skills/write/templates/README.md +408 -0
- package/src/skills/write/templates/UPSTREAM_LICENSE.txt +21 -0
- package/src/skills/write/templates/aaai2026/README.md +534 -0
- package/src/skills/write/templates/aaai2026/aaai2026-unified-supp.tex +144 -0
- package/src/skills/write/templates/aaai2026/aaai2026-unified-template.tex +952 -0
- package/src/skills/write/templates/aaai2026/aaai2026.bib +111 -0
- package/src/skills/write/templates/aaai2026/aaai2026.bst +1493 -0
- package/src/skills/write/templates/aaai2026/aaai2026.sty +315 -0
- package/src/skills/write/templates/acl/README.md +50 -0
- package/src/skills/write/templates/acl/acl.sty +312 -0
- package/src/skills/write/templates/acl/acl_latex.tex +377 -0
- package/src/skills/write/templates/acl/acl_lualatex.tex +101 -0
- package/src/skills/write/templates/acl/acl_natbib.bst +1940 -0
- package/src/skills/write/templates/acl/anthology.bib.txt +26 -0
- package/src/skills/write/templates/acl/custom.bib +70 -0
- package/src/skills/write/templates/acl/formatting.md +326 -0
- package/src/skills/write/templates/asplos2027/main.tex +459 -0
- package/src/skills/write/templates/asplos2027/references.bib +135 -0
- package/src/skills/write/templates/colm2025/README.md +3 -0
- package/src/skills/write/templates/colm2025/colm2025_conference.bib +11 -0
- package/src/skills/write/templates/colm2025/colm2025_conference.bst +1440 -0
- package/src/skills/write/templates/colm2025/colm2025_conference.sty +218 -0
- package/src/skills/write/templates/colm2025/colm2025_conference.tex +305 -0
- package/src/skills/write/templates/colm2025/fancyhdr.sty +485 -0
- package/src/skills/write/templates/colm2025/math_commands.tex +508 -0
- package/src/skills/write/templates/colm2025/natbib.sty +1246 -0
- package/src/skills/write/templates/iclr2026/fancyhdr.sty +485 -0
- package/src/skills/write/templates/iclr2026/iclr2026_conference.bib +24 -0
- package/src/skills/write/templates/iclr2026/iclr2026_conference.bst +1440 -0
- package/src/skills/write/templates/iclr2026/iclr2026_conference.sty +246 -0
- package/src/skills/write/templates/iclr2026/iclr2026_conference.tex +414 -0
- package/src/skills/write/templates/iclr2026/math_commands.tex +508 -0
- package/src/skills/write/templates/iclr2026/natbib.sty +1246 -0
- package/src/skills/write/templates/icml2026/algorithm.sty +79 -0
- package/src/skills/write/templates/icml2026/algorithmic.sty +201 -0
- package/src/skills/write/templates/icml2026/example_paper.bib +75 -0
- package/src/skills/write/templates/icml2026/example_paper.tex +662 -0
- package/src/skills/write/templates/icml2026/fancyhdr.sty +864 -0
- package/src/skills/write/templates/icml2026/icml2026.bst +1443 -0
- package/src/skills/write/templates/icml2026/icml2026.sty +767 -0
- package/src/skills/write/templates/neurips2025/Makefile +36 -0
- package/src/skills/write/templates/neurips2025/extra_pkgs.tex +53 -0
- package/src/skills/write/templates/neurips2025/main.tex +38 -0
- package/src/skills/write/templates/neurips2025/neurips.sty +382 -0
- package/src/skills/write/templates/nsdi2027/main.tex +426 -0
- package/src/skills/write/templates/nsdi2027/references.bib +151 -0
- package/src/skills/write/templates/nsdi2027/usenix-2020-09.sty +83 -0
- package/src/skills/write/templates/osdi2026/main.tex +429 -0
- package/src/skills/write/templates/osdi2026/references.bib +150 -0
- package/src/skills/write/templates/osdi2026/usenix-2020-09.sty +83 -0
- package/src/skills/write/templates/sosp2026/main.tex +532 -0
- package/src/skills/write/templates/sosp2026/references.bib +148 -0
- package/src/tui/package.json +1 -1
- package/src/ui/dist/assets/{AiManusChatView-BS3V4ZOk.js → AiManusChatView-m2FNtwbn.js} +110 -14
- package/src/ui/dist/assets/{AnalysisPlugin-DLPXQsmr.js → AnalysisPlugin-BMTF8EGL.js} +1 -1
- package/src/ui/dist/assets/{AutoFigurePlugin-C-Fr9knQ.js → AutoFigurePlugin-DxPdMUNb.js} +5 -5
- package/src/ui/dist/assets/{CliPlugin-Dd8AHzFg.js → CliPlugin-BEOWgxCI.js} +9 -9
- package/src/ui/dist/assets/{CodeEditorPlugin-Dg-RepTl.js → CodeEditorPlugin-BCXvjqmb.js} +8 -8
- package/src/ui/dist/assets/{CodeViewerPlugin-D2J_3nyt.js → CodeViewerPlugin-DaJcy3nD.js} +5 -5
- package/src/ui/dist/assets/{DocViewerPlugin-ChRLLKNb.js → DocViewerPlugin-ByfeIq4K.js} +3 -3
- package/src/ui/dist/assets/{GitDiffViewerPlugin-DgHfcved.js → GitDiffViewerPlugin-Cksf3VZ-.js} +830 -86
- package/src/ui/dist/assets/{ImageViewerPlugin-C89GZMBy.js → ImageViewerPlugin-CFz-OsTS.js} +5 -5
- package/src/ui/dist/assets/{LabCopilotPanel-BUfIwUcb.js → LabCopilotPanel-CJ1cJzoX.js} +10 -10
- package/src/ui/dist/assets/{LabPlugin-zvUmQUMq.js → LabPlugin-BF3dVJwa.js} +1 -1
- package/src/ui/dist/assets/{LatexPlugin-C1SSNuWp.js → LatexPlugin-DDkwZ6Sj.js} +7 -7
- package/src/ui/dist/assets/{MarkdownViewerPlugin-D2Mf5tU5.js → MarkdownViewerPlugin-HAuvurcT.js} +4 -4
- package/src/ui/dist/assets/{MarketplacePlugin-CF4LgiS2.js → MarketplacePlugin-BtoTYy2C.js} +3 -3
- package/src/ui/dist/assets/{index-Be0NAmh8.js → NotebookEditor-CSJYx7b-.js} +12 -155
- package/src/ui/dist/assets/{NotebookEditor-BM7Bgwlv.js → NotebookEditor-DQgRezm_.js} +1 -1
- package/src/ui/dist/assets/{PdfLoader-Bc5qfD-Z.js → PdfLoader-DPa_-fv6.js} +1 -1
- package/src/ui/dist/assets/{PdfMarkdownPlugin-sh1-IRcp.js → PdfMarkdownPlugin-BZpXOEjm.js} +3 -3
- package/src/ui/dist/assets/{PdfViewerPlugin-C_a7CpWG.js → PdfViewerPlugin-BT8a6wGR.js} +10 -10
- package/src/ui/dist/assets/{SearchPlugin-L4z3HcLf.js → SearchPlugin-D_blveZi.js} +1 -1
- package/src/ui/dist/assets/{Stepper-Dk4aQ3fN.js → Stepper-DH2k75Vo.js} +1 -1
- package/src/ui/dist/assets/{TextViewerPlugin-BsNtlKVo.js → TextViewerPlugin-Btx0M3hX.js} +4 -4
- package/src/ui/dist/assets/{VNCViewer-BpeDcZ5_.js → VNCViewer-DImJO4rO.js} +9 -9
- package/src/ui/dist/assets/{bibtex-C4QI-bbj.js → bibtex-B-Hqu0Sg.js} +1 -1
- package/src/ui/dist/assets/{code-DuMINRsg.js → code-BUfXGJSl.js} +1 -1
- package/src/ui/dist/assets/{file-content-C3N-432K.js → file-content-VqamwI3X.js} +1 -1
- package/src/ui/dist/assets/{file-diff-panel-CffQ4ZMg.js → file-diff-panel-C_wOoS7a.js} +1 -1
- package/src/ui/dist/assets/{file-socket-CRH59PCO.js → file-socket-D2bTuMVP.js} +1 -1
- package/src/ui/dist/assets/{file-utils-vYGtW2mI.js → file-utils--zJCPN1i.js} +1 -1
- package/src/ui/dist/assets/{image-DBVGaooo.js → image-BZkGJ4mM.js} +1 -1
- package/src/ui/dist/assets/{index-DjSFDmgB.js → index-CxkvSeKw.js} +2 -2
- package/src/ui/dist/assets/{index-BpjYH9Vg.js → index-D9QIGcmc.js} +1 -1
- package/src/ui/dist/assets/{index-Do9N28uB.css → index-DXZ1daiJ.css} +163 -34
- package/src/ui/dist/assets/index-DdRW6RMJ.js +159 -0
- package/src/ui/dist/assets/{index-B1P6hQRJ.js → index-DjggJovS.js} +3029 -1780
- package/src/ui/dist/assets/{message-square-BsPDBhiY.js → message-square-FUIPIhU2.js} +1 -1
- package/src/ui/dist/assets/{monaco-BTkdPojV.js → monaco-DHMc7kKM.js} +1 -1
- package/src/ui/dist/assets/{popover-cWjCk-vc.js → popover-B85oCgCS.js} +1 -1
- package/src/ui/dist/assets/{project-sync-CXn530xb.js → project-sync-DOMCcPac.js} +1 -1
- package/src/ui/dist/assets/{sigma-04Jr12jg.js → sigma-BO2rQrl3.js} +1 -1
- package/src/ui/dist/assets/{tooltip-BdVDl0G5.js → tooltip-B1OspAkx.js} +1 -1
- package/src/ui/dist/assets/{trash-CB_GlQyC.js → trash-BsVEH_dV.js} +1 -1
- package/src/ui/dist/assets/{useCliAccess-BL932NwS.js → useCliAccess-b8L6JuZm.js} +1 -1
- package/src/ui/dist/assets/{useFileDiffOverlay-B2WK7Tvq.js → useFileDiffOverlay-BY7uA9hV.js} +1 -1
- package/src/ui/dist/assets/{wrap-text-YC68g12z.js → wrap-text-BwyVuUIK.js} +1 -1
- package/src/ui/dist/assets/{zoom-out-C0RJvFiJ.js → zoom-out-RDpLugQP.js} +1 -1
- package/src/ui/dist/index.html +5 -2
- /package/src/ui/dist/assets/{index-CccQYZjX.css → NotebookEditor-CccQYZjX.css} +0 -0
|
@@ -6,10 +6,94 @@ from typing import Any
|
|
|
6
6
|
from mcp.server.fastmcp import FastMCP
|
|
7
7
|
|
|
8
8
|
from ..artifact import ArtifactService
|
|
9
|
+
from ..artifact.metrics import MetricContractValidationError
|
|
9
10
|
from ..bash_exec import BashExecService
|
|
10
11
|
from ..memory import MemoryService
|
|
11
12
|
from .context import McpContext
|
|
12
13
|
|
|
14
|
+
DEFAULT_INLINE_BASH_LOG_LINE_LIMIT = 2000
|
|
15
|
+
DEFAULT_INLINE_BASH_LOG_HEAD_LINES = 500
|
|
16
|
+
DEFAULT_INLINE_BASH_LOG_TAIL_LINES = 1500
|
|
17
|
+
DEFAULT_INLINE_BASH_LOG_WINDOW_LINES = 200
|
|
18
|
+
MAX_INLINE_BASH_LOG_WINDOW_LINES = 2000
|
|
19
|
+
LONG_BASH_LOG_HINT = (
|
|
20
|
+
"Use `bash_exec(mode='read', id=..., start=..., tail=...)` to inspect a specific log window, "
|
|
21
|
+
"or `bash_exec(mode='read', id=..., tail=...)` to inspect the latest rendered lines."
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _metric_validation_error_payload(exc: MetricContractValidationError) -> dict[str, Any]:
|
|
26
|
+
return exc.as_payload()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _split_bash_log_lines(log_text: str) -> list[str]:
|
|
30
|
+
return log_text.splitlines()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _join_bash_log_lines(lines: list[str]) -> str:
|
|
34
|
+
return "\n".join(lines)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _normalize_bash_log_window_size(value: int | None, *, default: int = DEFAULT_INLINE_BASH_LOG_WINDOW_LINES) -> int:
|
|
38
|
+
resolved = default if value is None else int(value)
|
|
39
|
+
return max(1, min(resolved, MAX_INLINE_BASH_LOG_WINDOW_LINES))
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _build_bash_log_window(log_text: str, *, start: int | None = None, tail: int | None = None) -> dict[str, Any]:
|
|
43
|
+
lines = _split_bash_log_lines(log_text)
|
|
44
|
+
total = len(lines)
|
|
45
|
+
line_limit = _normalize_bash_log_window_size(tail)
|
|
46
|
+
if start is not None:
|
|
47
|
+
requested_start = max(1, int(start))
|
|
48
|
+
start_index = min(max(0, requested_start - 1), total)
|
|
49
|
+
else:
|
|
50
|
+
start_index = max(0, total - line_limit)
|
|
51
|
+
selected = lines[start_index : start_index + line_limit]
|
|
52
|
+
returned_count = len(selected)
|
|
53
|
+
line_start = start_index + 1 if total else 1
|
|
54
|
+
line_end = start_index + returned_count
|
|
55
|
+
return {
|
|
56
|
+
"log": _join_bash_log_lines(selected),
|
|
57
|
+
"log_line_count": total,
|
|
58
|
+
"log_windowed": True,
|
|
59
|
+
"line_start": line_start,
|
|
60
|
+
"line_end": line_end,
|
|
61
|
+
"line_limit": line_limit,
|
|
62
|
+
"returned_line_count": returned_count,
|
|
63
|
+
"has_more_before": start_index > 0,
|
|
64
|
+
"has_more_after": line_end < total,
|
|
65
|
+
"log_read_hint": LONG_BASH_LOG_HINT,
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _build_default_bash_log_payload(log_text: str) -> dict[str, Any]:
|
|
70
|
+
lines = _split_bash_log_lines(log_text)
|
|
71
|
+
total = len(lines)
|
|
72
|
+
if total <= DEFAULT_INLINE_BASH_LOG_LINE_LIMIT:
|
|
73
|
+
return {
|
|
74
|
+
"log": log_text,
|
|
75
|
+
"log_line_count": total,
|
|
76
|
+
"log_truncated": False,
|
|
77
|
+
}
|
|
78
|
+
omitted = total - DEFAULT_INLINE_BASH_LOG_HEAD_LINES - DEFAULT_INLINE_BASH_LOG_TAIL_LINES
|
|
79
|
+
marker = (
|
|
80
|
+
f"[... omitted {omitted} lines from the middle of this log. {LONG_BASH_LOG_HINT}]"
|
|
81
|
+
)
|
|
82
|
+
preview_lines = (
|
|
83
|
+
lines[:DEFAULT_INLINE_BASH_LOG_HEAD_LINES]
|
|
84
|
+
+ [marker]
|
|
85
|
+
+ lines[-DEFAULT_INLINE_BASH_LOG_TAIL_LINES :]
|
|
86
|
+
)
|
|
87
|
+
return {
|
|
88
|
+
"log": _join_bash_log_lines(preview_lines),
|
|
89
|
+
"log_line_count": total,
|
|
90
|
+
"log_truncated": True,
|
|
91
|
+
"log_preview_head_lines": DEFAULT_INLINE_BASH_LOG_HEAD_LINES,
|
|
92
|
+
"log_preview_tail_lines": DEFAULT_INLINE_BASH_LOG_TAIL_LINES,
|
|
93
|
+
"log_preview_omitted_lines": omitted,
|
|
94
|
+
"log_read_hint": LONG_BASH_LOG_HINT,
|
|
95
|
+
}
|
|
96
|
+
|
|
13
97
|
|
|
14
98
|
def build_memory_server(context: McpContext) -> FastMCP:
|
|
15
99
|
service = MemoryService(context.home)
|
|
@@ -200,6 +284,32 @@ def build_artifact_server(context: McpContext) -> FastMCP:
|
|
|
200
284
|
start_point=start_point,
|
|
201
285
|
)
|
|
202
286
|
|
|
287
|
+
@server.tool(
|
|
288
|
+
name="activate_branch",
|
|
289
|
+
description=(
|
|
290
|
+
"Activate one existing durable research branch as the current workspace without creating a new lineage node. "
|
|
291
|
+
"Use this when you need to revisit an older idea/main-result branch for more experiments or a fresh decision."
|
|
292
|
+
),
|
|
293
|
+
)
|
|
294
|
+
def activate_branch(
|
|
295
|
+
branch: str | None = None,
|
|
296
|
+
idea_id: str | None = None,
|
|
297
|
+
run_id: str | None = None,
|
|
298
|
+
anchor: str | None = "auto",
|
|
299
|
+
promote_to_head: bool = False,
|
|
300
|
+
create_worktree_if_missing: bool = True,
|
|
301
|
+
comment: str | dict[str, Any] | None = None,
|
|
302
|
+
) -> dict[str, Any]:
|
|
303
|
+
return service.activate_branch(
|
|
304
|
+
context.require_quest_root(),
|
|
305
|
+
branch=branch,
|
|
306
|
+
idea_id=idea_id,
|
|
307
|
+
run_id=run_id,
|
|
308
|
+
anchor=anchor,
|
|
309
|
+
promote_to_head=promote_to_head,
|
|
310
|
+
create_worktree_if_missing=create_worktree_if_missing,
|
|
311
|
+
)
|
|
312
|
+
|
|
203
313
|
@server.tool(
|
|
204
314
|
name="submit_idea",
|
|
205
315
|
description=(
|
|
@@ -310,29 +420,33 @@ def build_artifact_server(context: McpContext) -> FastMCP:
|
|
|
310
420
|
evaluation_summary: dict[str, Any] | None = None,
|
|
311
421
|
comment: str | dict[str, Any] | None = None,
|
|
312
422
|
) -> dict[str, Any]:
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
423
|
+
try:
|
|
424
|
+
return service.record_main_experiment(
|
|
425
|
+
context.require_quest_root(),
|
|
426
|
+
run_id=run_id,
|
|
427
|
+
title=title,
|
|
428
|
+
hypothesis=hypothesis,
|
|
429
|
+
setup=setup,
|
|
430
|
+
execution=execution,
|
|
431
|
+
results=results,
|
|
432
|
+
conclusion=conclusion,
|
|
433
|
+
metric_rows=metric_rows,
|
|
434
|
+
metrics_summary=metrics_summary,
|
|
435
|
+
metric_contract=metric_contract,
|
|
436
|
+
evidence_paths=evidence_paths,
|
|
437
|
+
changed_files=changed_files,
|
|
438
|
+
config_paths=config_paths,
|
|
439
|
+
notes=notes,
|
|
440
|
+
dataset_scope=dataset_scope,
|
|
441
|
+
verdict=verdict,
|
|
442
|
+
status=status,
|
|
443
|
+
baseline_id=baseline_id,
|
|
444
|
+
baseline_variant_id=baseline_variant_id,
|
|
445
|
+
evaluation_summary=evaluation_summary,
|
|
446
|
+
strict_metric_contract=True,
|
|
447
|
+
)
|
|
448
|
+
except MetricContractValidationError as exc:
|
|
449
|
+
return _metric_validation_error_payload(exc)
|
|
336
450
|
|
|
337
451
|
@server.tool(
|
|
338
452
|
name="create_analysis_campaign",
|
|
@@ -527,19 +641,23 @@ def build_artifact_server(context: McpContext) -> FastMCP:
|
|
|
527
641
|
auto_advance: bool = True,
|
|
528
642
|
comment: str | dict[str, Any] | None = None,
|
|
529
643
|
) -> dict[str, Any]:
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
644
|
+
try:
|
|
645
|
+
return service.confirm_baseline(
|
|
646
|
+
context.require_quest_root(),
|
|
647
|
+
baseline_path=baseline_path,
|
|
648
|
+
comment=comment,
|
|
649
|
+
baseline_id=baseline_id,
|
|
650
|
+
variant_id=variant_id,
|
|
651
|
+
summary=summary,
|
|
652
|
+
baseline_kind=baseline_kind,
|
|
653
|
+
metric_contract=metric_contract,
|
|
654
|
+
metrics_summary=metrics_summary,
|
|
655
|
+
primary_metric=primary_metric,
|
|
656
|
+
auto_advance=auto_advance,
|
|
657
|
+
strict_metric_contract=True,
|
|
658
|
+
)
|
|
659
|
+
except MetricContractValidationError as exc:
|
|
660
|
+
return _metric_validation_error_payload(exc)
|
|
543
661
|
|
|
544
662
|
@server.tool(
|
|
545
663
|
name="waive_baseline",
|
|
@@ -661,7 +779,10 @@ def build_bash_exec_server(context: McpContext) -> FastMCP:
|
|
|
661
779
|
description=(
|
|
662
780
|
"Execute a bash command inside the current quest. "
|
|
663
781
|
"mode=detach returns immediately. mode=await/create waits for completion. "
|
|
664
|
-
"mode=read returns the saved log
|
|
782
|
+
"mode=read returns the saved log. It returns the full saved log up to 2000 lines, "
|
|
783
|
+
"or a 500-line head plus 1500-line tail preview for longer logs. "
|
|
784
|
+
"Use start/tail for rendered line windows and tail_limit/after_seq for seq-based monitoring. "
|
|
785
|
+
"mode=kill requests termination. "
|
|
665
786
|
"mode=list shows known quest-local bash sessions. mode=history shows a compact reverse-chronological bash id list."
|
|
666
787
|
),
|
|
667
788
|
)
|
|
@@ -681,6 +802,8 @@ def build_bash_exec_server(context: McpContext) -> FastMCP:
|
|
|
681
802
|
agent_instance_ids: list[str] | None = None,
|
|
682
803
|
chat_session_id: str | None = None,
|
|
683
804
|
limit: int = 20,
|
|
805
|
+
start: int | None = None,
|
|
806
|
+
tail: int | None = None,
|
|
684
807
|
tail_limit: int | None = None,
|
|
685
808
|
before_seq: int | None = None,
|
|
686
809
|
after_seq: int | None = None,
|
|
@@ -732,6 +855,29 @@ def build_bash_exec_server(context: McpContext) -> FastMCP:
|
|
|
732
855
|
normalized_order = (order or "asc").strip().lower()
|
|
733
856
|
if normalized_order not in {"asc", "desc"}:
|
|
734
857
|
normalized_order = "asc"
|
|
858
|
+
if tail is not None and tail_limit is not None:
|
|
859
|
+
raise ValueError("Use either `tail` or `tail_limit`, not both.")
|
|
860
|
+
use_line_window = start is not None or tail is not None or (start is not None and tail_limit is not None)
|
|
861
|
+
if use_line_window and (before_seq is not None or after_seq is not None):
|
|
862
|
+
raise ValueError("`start`/`tail` cannot be combined with `before_seq` or `after_seq`.")
|
|
863
|
+
if use_line_window and normalized_order != "asc":
|
|
864
|
+
raise ValueError("`start`/`tail` windows only support `order='asc'`.")
|
|
865
|
+
if use_line_window:
|
|
866
|
+
payload = service.build_tool_result(
|
|
867
|
+
context,
|
|
868
|
+
session=session,
|
|
869
|
+
include_log=False,
|
|
870
|
+
export_log=export_log,
|
|
871
|
+
export_log_to=export_log_to,
|
|
872
|
+
)
|
|
873
|
+
payload.update(
|
|
874
|
+
_build_bash_log_window(
|
|
875
|
+
service.read_terminal_log(quest_root, bash_id),
|
|
876
|
+
start=start,
|
|
877
|
+
tail=tail if tail is not None else tail_limit,
|
|
878
|
+
)
|
|
879
|
+
)
|
|
880
|
+
return payload
|
|
735
881
|
use_tail = tail_limit is not None or before_seq is not None or after_seq is not None or normalized_order != "asc"
|
|
736
882
|
if use_tail:
|
|
737
883
|
resolved_tail_limit = max(1, min(int(tail_limit or 200), 1000))
|
|
@@ -742,6 +888,7 @@ def build_bash_exec_server(context: McpContext) -> FastMCP:
|
|
|
742
888
|
before_seq=before_seq,
|
|
743
889
|
after_seq=after_seq,
|
|
744
890
|
order=normalized_order,
|
|
891
|
+
prefer_visible=True,
|
|
745
892
|
)
|
|
746
893
|
payload = service.build_tool_result(
|
|
747
894
|
context,
|
|
@@ -758,13 +905,15 @@ def build_bash_exec_server(context: McpContext) -> FastMCP:
|
|
|
758
905
|
payload["before_seq"] = tail_meta.get("before_seq")
|
|
759
906
|
payload["order"] = normalized_order
|
|
760
907
|
return payload
|
|
761
|
-
|
|
908
|
+
payload = service.build_tool_result(
|
|
762
909
|
context,
|
|
763
910
|
session=session,
|
|
764
|
-
include_log=
|
|
911
|
+
include_log=False,
|
|
765
912
|
export_log=export_log,
|
|
766
913
|
export_log_to=export_log_to,
|
|
767
914
|
)
|
|
915
|
+
payload.update(_build_default_bash_log_payload(service.read_terminal_log(quest_root, bash_id)))
|
|
916
|
+
return payload
|
|
768
917
|
if normalized_mode == "kill":
|
|
769
918
|
bash_id = service.resolve_session_id(quest_root, id)
|
|
770
919
|
session = service.request_stop(
|
|
@@ -92,10 +92,16 @@ class PromptBuilder:
|
|
|
92
92
|
active_anchor = str(snapshot.get("active_anchor") or skill_id)
|
|
93
93
|
default_locale = str(runtime_config.get("default_locale") or "en-US")
|
|
94
94
|
system_block = self._prompt_fragment("system.md", quest_root=quest_root)
|
|
95
|
+
shared_interaction_block = self._prompt_fragment(
|
|
96
|
+
Path("contracts") / "shared_interaction.md",
|
|
97
|
+
quest_root=quest_root,
|
|
98
|
+
)
|
|
95
99
|
connector_contract_block = self._connector_contract_block(quest_id=quest_id, snapshot=snapshot)
|
|
96
100
|
sections = [
|
|
97
101
|
system_block,
|
|
98
102
|
"",
|
|
103
|
+
shared_interaction_block,
|
|
104
|
+
"",
|
|
99
105
|
"## Runtime Context",
|
|
100
106
|
f"ds_home: {self.home.resolve()}",
|
|
101
107
|
f"quest_id: {quest_id}",
|
|
@@ -718,6 +724,11 @@ class PromptBuilder:
|
|
|
718
724
|
[
|
|
719
725
|
"- delivery_goal: the quest should normally continue until at least one paper-like deliverable exists.",
|
|
720
726
|
"- main_result_rule: a strong main experiment is evidence, not the endpoint; usually continue into the necessary analysis, writing, or further strengthening work.",
|
|
727
|
+
"- main_run_branch_rule: every durable main experiment should live on its own dedicated `run/*` branch/worktree so the result becomes a stable Canvas node instead of mutating the idea branch in place.",
|
|
728
|
+
"- main_run_branch_rule_2: if the current workspace is still an idea branch when `artifact.record_main_experiment(...)` runs, the runtime will materialize a child `run/*` branch before durable recording; still prefer planning and implementation with that dedicated run branch in mind from the start.",
|
|
729
|
+
"- paper_branch_rule: after the required analysis for a strong main result is complete, writing should continue on a dedicated `paper/*` branch/worktree derived from that run branch rather than on the quest root or on the evidence branch itself.",
|
|
730
|
+
"- paper_branch_rule_2: treat the paper branch as the writing surface and the parent run branch as the evidence source; do not record new main experiments from the paper branch.",
|
|
731
|
+
"- paper_template_rule: once paper writing starts, choose a real venue template from the `write` skill's `templates/` folder, copy it into `paper/latex/`, and default to `templates/iclr2026/` for general ML unless the user or venue contract clearly points elsewhere.",
|
|
721
732
|
"- writing_rule: when the evidence becomes strong enough, analysis and paper writing remain in scope by default.",
|
|
722
733
|
"- review_gate_rule: before declaring a substantial paper/draft task done, open `review` for an independent skeptical audit; if that audit finds serious gaps, route to `analysis-campaign`, `baseline`, `scout`, or `write` instead of stopping.",
|
|
723
734
|
"- stop_rule: do not stop with only an improved algorithm or isolated run logs unless the user explicitly narrows scope.",
|
|
@@ -755,15 +766,17 @@ class PromptBuilder:
|
|
|
755
766
|
"- interaction_protocol: first message may be plain conversation; after that, treat artifact.interact threads and mailbox polls as the main continuity spine across TUI, web, and connectors",
|
|
756
767
|
"- mailbox_protocol: artifact.interact(include_recent_inbound_messages=True) is the queued human-message mailbox; when it returns user text, treat that input as higher priority than background subtasks until it has been acknowledged",
|
|
757
768
|
"- acknowledgment_protocol: after artifact.interact returns any human message, immediately send one substantive artifact.interact(...) follow-up; if the active connector runtime already emitted a transport-level receipt acknowledgement, do not send a redundant receipt-only message; if answerable, answer directly, otherwise state the short plan, nearest checkpoint, and that the current background subtask is paused",
|
|
758
|
-
"- progress_protocol: emit artifact.interact(kind='progress', reply_mode='threaded', ...) at real human-meaningful checkpoints; if no natural checkpoint appears during active user-relevant work,
|
|
769
|
+
"- progress_protocol: emit artifact.interact(kind='progress', reply_mode='threaded', ...) at real human-meaningful checkpoints; if no natural checkpoint appears during active user-relevant work, prefer a concise keepalive once work has crossed roughly 10 tool calls with a human-meaningful delta, and do not drift beyond roughly 20 tool calls or about 15 minutes without a user-visible update",
|
|
759
770
|
"- smoke_then_detach_protocol: for baseline reproduction, main experiments, and analysis experiments, first validate the command path with a bounded smoke test; once the smoke test passes, launch the real long run with bash_exec(mode='detach', ...) and usually leave timeout_seconds unset rather than guessing a fake deadline",
|
|
760
771
|
"- progress_first_monitoring_protocol: when supervising a long-running bash_exec session, judge health by forward progress rather than by whether the final artifact has already appeared within a short window",
|
|
761
772
|
"- delta_monitoring_protocol: compare deltas such as new sample counters, new task counters, new saved files, new last_output_seq values, or changed last_progress payloads; if any of these move forward, treat the run as alive and keep observing",
|
|
762
|
-
"- long_run_reporting_protocol: for long-running bash_exec monitoring loops, inspect real logs or status after each completed sleep/await cycle and at least once every 30 minutes at worst, but only send a user-visible update when there is a human-meaningful delta or when the 30-minute visibility bound would otherwise be exceeded",
|
|
773
|
+
"- long_run_reporting_protocol: for long-running bash_exec monitoring loops, inspect real logs or status after each completed sleep/await cycle and at least once every 30 minutes at worst, but only send a user-visible update when there is a human-meaningful delta or when the 30-minute visibility bound would otherwise be exceeded; those updates should report the current status, the latest concrete evidence of progress or failure, and the next checkpoint",
|
|
763
774
|
"- long_run_watchdog_protocol: for baseline reproduction, baseline-running stages, main experiments, and other important detached runs, do not let more than 30 minutes pass without a real progress inspection and, if the run is still active, a user-visible artifact.interact progress update",
|
|
764
775
|
"- intervention_threshold_protocol: do not kill or restart a run merely because a short watch window passed without final completion; intervene only on explicit failure, clear invalidity, process exit, or no meaningful delta across a sufficiently long observation window",
|
|
765
776
|
"- slow_model_patience_protocol: if the user says the model, endpoint, or workload is expected to be slow, widen the observation window before intervention and avoid repeated no-change updates",
|
|
766
|
-
"-
|
|
777
|
+
"- saved_log_read_protocol: bash_exec(mode='read', id=...) returns the full saved rendered log when it is 2000 lines or fewer; for longer logs it returns a preview with the first 500 lines plus the last 1500 lines and tells you to use start/tail for omitted middle windows",
|
|
778
|
+
"- log_window_protocol: when you need a specific omitted middle region from a long saved log, use bash_exec(mode='read', id=..., start=..., tail=...) to read a forward rendered-line window",
|
|
779
|
+
"- tail_monitoring_protocol: when monitoring a detached run, prefer bash_exec(mode='read', id=..., tail_limit=..., order='desc') so you inspect the newest seq-based evidence first instead of re-reading full logs every time",
|
|
767
780
|
"- managed_recovery_protocol: if a detached baseline, main-experiment, or analysis run is clearly invalid, wedged, or superseded, stop it with bash_exec(mode='kill', id=...), document the reason, fix the issue, and relaunch cleanly instead of letting a bad run linger",
|
|
768
781
|
"- timeout_protocol: before using bash_exec(mode='await', ...), estimate whether the command can finish within the selected wait window; if runtime is uncertain or likely longer, use bash_exec(mode='detach', ...) and monitor, or set timeout_seconds intentionally",
|
|
769
782
|
"- blocking_protocol: use reply_mode='blocking' only for true unresolved user decisions; ordinary progress updates should stay threaded and non-blocking",
|
|
@@ -774,8 +787,9 @@ class PromptBuilder:
|
|
|
774
787
|
"- respect_protocol: write user-facing updates as natural, respectful, easy-to-follow chat; do not sound like a formal status report or internal tool log",
|
|
775
788
|
"- omission_protocol: for ordinary user-facing updates, omit file paths, artifact ids, branch/worktree ids, session ids, raw commands, raw logs, and internal tool names unless the user asked for them or needs them to act",
|
|
776
789
|
"- compaction_protocol: ordinary artifact.interact progress updates should usually fit in 2 to 4 short sentences and should not read like a monitoring transcript or execution diary",
|
|
777
|
-
"- tool_call_keepalive_protocol: for active multi-step work outside long detached experiment waits,
|
|
790
|
+
"- tool_call_keepalive_protocol: for active multi-step work outside long detached experiment waits, prefer sending one concise artifact.interact progress update after roughly 10 tool calls when there is already a human-meaningful delta, and do not exceed roughly 20 tool calls or about 15 minutes without a user-visible checkpoint",
|
|
778
791
|
"- human_progress_shape_protocol: ordinary progress updates should usually make three things explicit in human language: the current task, the main difficulty or latest real progress, and the concrete next measure you will take",
|
|
792
|
+
"- milestone_graduation_protocol: keep ordinary subtask completions concise; upgrade to a richer milestone report only when a stage-significant deliverable or route-changing checkpoint becomes durably true",
|
|
779
793
|
"- eta_visibility_protocol: for baseline reproduction, main experiments, analysis experiments, and other important long-running phases, progress updates should also make the expected time to the next meaningful result, next milestone, or next user-visible update explicit; use roughly 10 to 30 minutes as the normal update window, and if the ETA is unreliable, say that and give a realistic next check-in window instead",
|
|
780
794
|
"- stage_plan_protocol: for `baseline`, `experiment`, and `analysis-campaign`, do not jump straight into substantial setup, code changes, or real runs; first create or update quest-visible `PLAN.md` and `CHECKLIST.md`, then keep them aligned with the actual route",
|
|
781
795
|
"- baseline_plan_protocol: in `baseline`, read the source paper and source repo first when they exist, then make `PLAN.md` cover the route, source package, code touchpoints, smoke path, real-run path, fallback options, monitoring rules, and verification targets before substantial work continues",
|
|
@@ -783,6 +797,7 @@ class PromptBuilder:
|
|
|
783
797
|
"- analysis_plan_protocol: in `analysis-campaign`, treat `PLAN.md` as the campaign charter and make it cover the slice list, comparability boundary, asset and comparator plan, smoke / full-run policy, reporting plan, and revision log before real slices launch",
|
|
784
798
|
"- checklist_maintenance_protocol: for those same stages, treat `CHECKLIST.md` as the living execution surface and update it during reading, setup, coding, smoke tests, real runs, validation, aggregation, and route changes instead of letting progress live only in chat",
|
|
785
799
|
"- plan_revision_protocol: if the route, comparability contract, source package, execution strategy, slice ordering, or campaign interpretation changes materially, revise `PLAN.md` before continuing",
|
|
800
|
+
"- plan_execution_stability_protocol: once `baseline` or `experiment` has a concrete `PLAN.md` route, implement that plan cleanly instead of repeatedly reshaping code and commands mid-flight; the normal default is one bounded smoke or pilot validation and then one real run, and extra retries should happen only after concrete failure, invalidity, or genuinely new evidence justifies them",
|
|
786
801
|
"- stage_milestone_summary_protocol: for accepted baseline, selected idea, completed main experiment, and completed analysis-campaign milestones, usually open with 1 to 2 sentences that say what happened, what it means, and the exact next step before expanding into more detail",
|
|
787
802
|
"- idea_milestone_protocol: immediately after a successful accepted artifact.submit_idea(...), send a threaded milestone that explains the idea in plain language and explicitly states whether it currently looks valid, research-worthy, and insight-bearing, plus the main risk and exact next experiment",
|
|
788
803
|
"- idea_divergence_protocol: in the idea stage, separate divergence from convergence; unless strong durable evidence already narrows the route to one obvious serious option, do not collapse onto the first plausible route before generating a small but meaningfully diverse candidate slate",
|
|
@@ -792,6 +807,8 @@ class PromptBuilder:
|
|
|
792
807
|
"- idea_balance_protocol: when the search space is not tiny, carry at least one conservative route and one higher-upside route into the final comparison",
|
|
793
808
|
"- idea_pitch_protocol: before artifact.submit_idea(...), make the winner pass a two-sentence pitch, a strongest-objection check, and a concrete why-now statement",
|
|
794
809
|
"- experiment_milestone_protocol: immediately after artifact.record_main_experiment(...) writes the durable result, send a threaded milestone that explains what was run, the main result, whether primary performance improved / worsened / stayed mixed versus the active baseline or best prior anchor, whether the route still looks promising, and the exact next step",
|
|
810
|
+
"- analysis_milestone_protocol: immediately after a meaningful completed analysis-campaign synthesis or route-significant campaign checkpoint, send a threaded milestone that explains which campaign question or slice set just closed, whether the claim boundary became stronger / weaker / mixed, the main caveat, and the exact next route",
|
|
811
|
+
"- paper_milestone_protocol: immediately after a meaningful paper or draft milestone such as selected outline, evidence-complete draft, major revision package, or bundle-ready paper, send a threaded milestone that explains what document milestone is now complete, which claims are now supportable, what still needs strengthening, and the exact next revision or execution route",
|
|
795
812
|
"- asset_grounded_analysis_protocol: before artifact.create_analysis_campaign(...), reuse current quest and user-provided assets first and only plan slices that are executable with the current assets, runtime/tooling, and available credentials",
|
|
796
813
|
"- infeasible_slice_protocol: if an analysis slice cannot actually be executed after bounded recovery, do not fake completion; record the slice with a non-success status, report the blocker explicitly, and do not pretend the system can do it",
|
|
797
814
|
"- explicit_improvement_protocol: never make the user infer performance improvement only from raw metrics; say plainly whether performance improved, worsened, or stayed mixed",
|
|
@@ -1076,7 +1093,13 @@ class PromptBuilder:
|
|
|
1076
1093
|
return "\n".join(lines)
|
|
1077
1094
|
|
|
1078
1095
|
def _paper_and_evidence_block(self, snapshot: dict, quest_root: Path) -> str:
|
|
1079
|
-
|
|
1096
|
+
workspace_root = Path(str(snapshot.get("active_workspace_root") or quest_root))
|
|
1097
|
+
paper_root = workspace_root / "paper"
|
|
1098
|
+
if not paper_root.exists():
|
|
1099
|
+
paper_root = quest_root / "paper"
|
|
1100
|
+
open_source_root = workspace_root / "release" / "open_source"
|
|
1101
|
+
if not open_source_root.exists():
|
|
1102
|
+
open_source_root = quest_root / "release" / "open_source"
|
|
1080
1103
|
selected_outline = read_json(paper_root / "selected_outline.json", {})
|
|
1081
1104
|
selected_outline = selected_outline if isinstance(selected_outline, dict) else {}
|
|
1082
1105
|
detailed_outline = (
|
|
@@ -1092,8 +1115,18 @@ class PromptBuilder:
|
|
|
1092
1115
|
claim_evidence_map = claim_evidence_map if isinstance(claim_evidence_map, dict) else {}
|
|
1093
1116
|
compile_report = read_json(paper_root / "build" / "compile_report.json", {})
|
|
1094
1117
|
compile_report = compile_report if isinstance(compile_report, dict) else {}
|
|
1095
|
-
open_source_manifest = read_json(
|
|
1118
|
+
open_source_manifest = read_json(open_source_root / "manifest.json", {})
|
|
1096
1119
|
open_source_manifest = open_source_manifest if isinstance(open_source_manifest, dict) else {}
|
|
1120
|
+
default_paper_prefix = (
|
|
1121
|
+
paper_root.relative_to(quest_root).as_posix()
|
|
1122
|
+
if paper_root.is_relative_to(quest_root)
|
|
1123
|
+
else "paper"
|
|
1124
|
+
)
|
|
1125
|
+
default_release_prefix = (
|
|
1126
|
+
open_source_root.relative_to(quest_root).as_posix()
|
|
1127
|
+
if open_source_root.is_relative_to(quest_root)
|
|
1128
|
+
else "release/open_source"
|
|
1129
|
+
)
|
|
1097
1130
|
|
|
1098
1131
|
selected_outline_ref = str(
|
|
1099
1132
|
selected_outline.get("outline_id") or bundle_manifest.get("selected_outline_ref") or ""
|
|
@@ -1130,14 +1163,14 @@ class PromptBuilder:
|
|
|
1130
1163
|
|
|
1131
1164
|
lines.extend(
|
|
1132
1165
|
[
|
|
1133
|
-
f"- writing_plan_status: {_path_status(bundle_manifest.get('writing_plan_path'), fallback='
|
|
1134
|
-
f"- draft_status: {_path_status(bundle_manifest.get('draft_path'), fallback='
|
|
1135
|
-
f"- references_status: {_path_status(bundle_manifest.get('references_path'), fallback='
|
|
1136
|
-
f"- claim_evidence_map_status: {_path_status(bundle_manifest.get('claim_evidence_map_path'), fallback='
|
|
1137
|
-
f"- baseline_inventory_status: {_path_status(bundle_manifest.get('baseline_inventory_path'), fallback='
|
|
1138
|
-
f"- review_status: {'
|
|
1139
|
-
f"- proofing_report_status: {'
|
|
1140
|
-
f"- page_images_manifest_status: {'
|
|
1166
|
+
f"- writing_plan_status: {_path_status(bundle_manifest.get('writing_plan_path'), fallback=f'{default_paper_prefix}/writing_plan.md')}",
|
|
1167
|
+
f"- draft_status: {_path_status(bundle_manifest.get('draft_path'), fallback=f'{default_paper_prefix}/draft.md')}",
|
|
1168
|
+
f"- references_status: {_path_status(bundle_manifest.get('references_path'), fallback=f'{default_paper_prefix}/references.bib')}",
|
|
1169
|
+
f"- claim_evidence_map_status: {_path_status(bundle_manifest.get('claim_evidence_map_path'), fallback=f'{default_paper_prefix}/claim_evidence_map.json')}",
|
|
1170
|
+
f"- baseline_inventory_status: {_path_status(bundle_manifest.get('baseline_inventory_path'), fallback=f'{default_paper_prefix}/baseline_inventory.json')}",
|
|
1171
|
+
f"- review_status: {f'{default_paper_prefix}/review/review.md [exists]' if (paper_root / 'review' / 'review.md').exists() else f'{default_paper_prefix}/review/review.md [missing]'}",
|
|
1172
|
+
f"- proofing_report_status: {f'{default_paper_prefix}/proofing/proofing_report.md [exists]' if (paper_root / 'proofing' / 'proofing_report.md').exists() else f'{default_paper_prefix}/proofing/proofing_report.md [missing]'}",
|
|
1173
|
+
f"- page_images_manifest_status: {f'{default_paper_prefix}/proofing/page_images_manifest.json [exists]' if (paper_root / 'proofing' / 'page_images_manifest.json').exists() else f'{default_paper_prefix}/proofing/page_images_manifest.json [missing]'}",
|
|
1141
1174
|
]
|
|
1142
1175
|
)
|
|
1143
1176
|
|
|
@@ -1148,11 +1181,11 @@ class PromptBuilder:
|
|
|
1148
1181
|
lines.extend(
|
|
1149
1182
|
[
|
|
1150
1183
|
"- paper_bundle_manifest_present: True",
|
|
1151
|
-
f"- bundle_pdf_status: {_path_status(pdf_rel_path, fallback='
|
|
1152
|
-
f"- bundle_compile_report_status: {_path_status(compile_rel_path, fallback='
|
|
1184
|
+
f"- bundle_pdf_status: {_path_status(pdf_rel_path, fallback=f'{default_paper_prefix}/paper.pdf')}",
|
|
1185
|
+
f"- bundle_compile_report_status: {_path_status(compile_rel_path, fallback=f'{default_paper_prefix}/build/compile_report.json')}",
|
|
1153
1186
|
f"- bundle_latex_root: {latex_root_path or 'none'}",
|
|
1154
|
-
f"- open_source_manifest_status: {_path_status(bundle_manifest.get('open_source_manifest_path'), fallback='
|
|
1155
|
-
f"- open_source_cleanup_plan_status: {_path_status(bundle_manifest.get('open_source_cleanup_plan_path'), fallback='
|
|
1187
|
+
f"- open_source_manifest_status: {_path_status(bundle_manifest.get('open_source_manifest_path'), fallback=f'{default_release_prefix}/manifest.json')}",
|
|
1188
|
+
f"- open_source_cleanup_plan_status: {_path_status(bundle_manifest.get('open_source_cleanup_plan_path'), fallback=f'{default_release_prefix}/cleanup_plan.md')}",
|
|
1156
1189
|
]
|
|
1157
1190
|
)
|
|
1158
1191
|
else:
|