@researai/deepscientist 1.5.7 → 1.5.9

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.
Files changed (156) hide show
  1. package/LICENSE +186 -21
  2. package/README.md +8 -4
  3. package/bin/ds.js +224 -9
  4. package/docs/en/00_QUICK_START.md +2 -2
  5. package/docs/en/07_MEMORY_AND_MCP.md +40 -3
  6. package/docs/en/99_ACKNOWLEDGEMENTS.md +1 -0
  7. package/docs/zh/00_QUICK_START.md +2 -2
  8. package/docs/zh/07_MEMORY_AND_MCP.md +40 -3
  9. package/docs/zh/99_ACKNOWLEDGEMENTS.md +1 -0
  10. package/install.sh +34 -0
  11. package/package.json +2 -2
  12. package/pyproject.toml +2 -2
  13. package/src/deepscientist/__init__.py +1 -1
  14. package/src/deepscientist/acp/envelope.py +1 -0
  15. package/src/deepscientist/artifact/metrics.py +814 -83
  16. package/src/deepscientist/artifact/schemas.py +1 -0
  17. package/src/deepscientist/artifact/service.py +2001 -229
  18. package/src/deepscientist/bash_exec/monitor.py +1 -1
  19. package/src/deepscientist/bash_exec/service.py +17 -9
  20. package/src/deepscientist/channels/qq.py +17 -0
  21. package/src/deepscientist/channels/relay.py +16 -0
  22. package/src/deepscientist/config/models.py +6 -0
  23. package/src/deepscientist/config/service.py +70 -2
  24. package/src/deepscientist/daemon/api/handlers.py +414 -14
  25. package/src/deepscientist/daemon/api/router.py +4 -0
  26. package/src/deepscientist/daemon/app.py +292 -21
  27. package/src/deepscientist/gitops/diff.py +6 -10
  28. package/src/deepscientist/mcp/server.py +191 -40
  29. package/src/deepscientist/prompts/builder.py +65 -19
  30. package/src/deepscientist/quest/node_traces.py +129 -2
  31. package/src/deepscientist/quest/service.py +140 -34
  32. package/src/deepscientist/quest/stage_views.py +175 -33
  33. package/src/deepscientist/registries/baseline.py +56 -4
  34. package/src/deepscientist/runners/codex.py +1 -1
  35. package/src/prompts/connectors/qq.md +1 -1
  36. package/src/prompts/contracts/shared_interaction.md +14 -0
  37. package/src/prompts/system.md +113 -32
  38. package/src/skills/analysis-campaign/SKILL.md +10 -14
  39. package/src/skills/baseline/SKILL.md +51 -38
  40. package/src/skills/baseline/references/baseline-plan-template.md +2 -0
  41. package/src/skills/decision/SKILL.md +12 -8
  42. package/src/skills/experiment/SKILL.md +28 -16
  43. package/src/skills/experiment/references/main-experiment-plan-template.md +2 -0
  44. package/src/skills/figure-polish/SKILL.md +1 -0
  45. package/src/skills/finalize/SKILL.md +3 -8
  46. package/src/skills/idea/SKILL.md +18 -8
  47. package/src/skills/idea/references/literature-survey-template.md +24 -0
  48. package/src/skills/idea/references/related-work-playbook.md +4 -0
  49. package/src/skills/idea/references/selection-gate.md +9 -0
  50. package/src/skills/intake-audit/SKILL.md +2 -8
  51. package/src/skills/rebuttal/SKILL.md +2 -8
  52. package/src/skills/review/SKILL.md +2 -8
  53. package/src/skills/scout/SKILL.md +2 -8
  54. package/src/skills/write/SKILL.md +53 -17
  55. package/src/skills/write/templates/DEEPSCIENTIST_NOTES.md +21 -0
  56. package/src/skills/write/templates/README.md +408 -0
  57. package/src/skills/write/templates/UPSTREAM_LICENSE.txt +21 -0
  58. package/src/skills/write/templates/aaai2026/README.md +534 -0
  59. package/src/skills/write/templates/aaai2026/aaai2026-unified-supp.tex +144 -0
  60. package/src/skills/write/templates/aaai2026/aaai2026-unified-template.tex +952 -0
  61. package/src/skills/write/templates/aaai2026/aaai2026.bib +111 -0
  62. package/src/skills/write/templates/aaai2026/aaai2026.bst +1493 -0
  63. package/src/skills/write/templates/aaai2026/aaai2026.sty +315 -0
  64. package/src/skills/write/templates/acl/README.md +50 -0
  65. package/src/skills/write/templates/acl/acl.sty +312 -0
  66. package/src/skills/write/templates/acl/acl_latex.tex +377 -0
  67. package/src/skills/write/templates/acl/acl_lualatex.tex +101 -0
  68. package/src/skills/write/templates/acl/acl_natbib.bst +1940 -0
  69. package/src/skills/write/templates/acl/anthology.bib.txt +26 -0
  70. package/src/skills/write/templates/acl/custom.bib +70 -0
  71. package/src/skills/write/templates/acl/formatting.md +326 -0
  72. package/src/skills/write/templates/asplos2027/main.tex +459 -0
  73. package/src/skills/write/templates/asplos2027/references.bib +135 -0
  74. package/src/skills/write/templates/colm2025/README.md +3 -0
  75. package/src/skills/write/templates/colm2025/colm2025_conference.bib +11 -0
  76. package/src/skills/write/templates/colm2025/colm2025_conference.bst +1440 -0
  77. package/src/skills/write/templates/colm2025/colm2025_conference.sty +218 -0
  78. package/src/skills/write/templates/colm2025/colm2025_conference.tex +305 -0
  79. package/src/skills/write/templates/colm2025/fancyhdr.sty +485 -0
  80. package/src/skills/write/templates/colm2025/math_commands.tex +508 -0
  81. package/src/skills/write/templates/colm2025/natbib.sty +1246 -0
  82. package/src/skills/write/templates/iclr2026/fancyhdr.sty +485 -0
  83. package/src/skills/write/templates/iclr2026/iclr2026_conference.bib +24 -0
  84. package/src/skills/write/templates/iclr2026/iclr2026_conference.bst +1440 -0
  85. package/src/skills/write/templates/iclr2026/iclr2026_conference.sty +246 -0
  86. package/src/skills/write/templates/iclr2026/iclr2026_conference.tex +414 -0
  87. package/src/skills/write/templates/iclr2026/math_commands.tex +508 -0
  88. package/src/skills/write/templates/iclr2026/natbib.sty +1246 -0
  89. package/src/skills/write/templates/icml2026/algorithm.sty +79 -0
  90. package/src/skills/write/templates/icml2026/algorithmic.sty +201 -0
  91. package/src/skills/write/templates/icml2026/example_paper.bib +75 -0
  92. package/src/skills/write/templates/icml2026/example_paper.tex +662 -0
  93. package/src/skills/write/templates/icml2026/fancyhdr.sty +864 -0
  94. package/src/skills/write/templates/icml2026/icml2026.bst +1443 -0
  95. package/src/skills/write/templates/icml2026/icml2026.sty +767 -0
  96. package/src/skills/write/templates/neurips2025/Makefile +36 -0
  97. package/src/skills/write/templates/neurips2025/extra_pkgs.tex +53 -0
  98. package/src/skills/write/templates/neurips2025/main.tex +38 -0
  99. package/src/skills/write/templates/neurips2025/neurips.sty +382 -0
  100. package/src/skills/write/templates/nsdi2027/main.tex +426 -0
  101. package/src/skills/write/templates/nsdi2027/references.bib +151 -0
  102. package/src/skills/write/templates/nsdi2027/usenix-2020-09.sty +83 -0
  103. package/src/skills/write/templates/osdi2026/main.tex +429 -0
  104. package/src/skills/write/templates/osdi2026/references.bib +150 -0
  105. package/src/skills/write/templates/osdi2026/usenix-2020-09.sty +83 -0
  106. package/src/skills/write/templates/sosp2026/main.tex +532 -0
  107. package/src/skills/write/templates/sosp2026/references.bib +148 -0
  108. package/src/tui/package.json +1 -1
  109. package/src/ui/dist/assets/{AiManusChatView-BS3V4ZOk.js → AiManusChatView-BKZ103sn.js} +110 -14
  110. package/src/ui/dist/assets/{AnalysisPlugin-DLPXQsmr.js → AnalysisPlugin-mTTzGAlK.js} +1 -1
  111. package/src/ui/dist/assets/{AutoFigurePlugin-C-Fr9knQ.js → AutoFigurePlugin-C_wWw4AP.js} +5 -5
  112. package/src/ui/dist/assets/{CliPlugin-Dd8AHzFg.js → CliPlugin-BH58n3GY.js} +9 -9
  113. package/src/ui/dist/assets/{CodeEditorPlugin-Dg-RepTl.js → CodeEditorPlugin-BKGRUH7e.js} +8 -8
  114. package/src/ui/dist/assets/{CodeViewerPlugin-D2J_3nyt.js → CodeViewerPlugin-BMADwFWJ.js} +5 -5
  115. package/src/ui/dist/assets/{DocViewerPlugin-ChRLLKNb.js → DocViewerPlugin-ZOnTIHLN.js} +3 -3
  116. package/src/ui/dist/assets/{GitDiffViewerPlugin-DgHfcved.js → GitDiffViewerPlugin-CQ7h1Djm.js} +830 -86
  117. package/src/ui/dist/assets/{ImageViewerPlugin-C89GZMBy.js → ImageViewerPlugin-GVS5MsnC.js} +5 -5
  118. package/src/ui/dist/assets/{LabCopilotPanel-BUfIwUcb.js → LabCopilotPanel-BZNv1JML.js} +10 -10
  119. package/src/ui/dist/assets/{LabPlugin-zvUmQUMq.js → LabPlugin-TWcJsdQA.js} +1 -1
  120. package/src/ui/dist/assets/{LatexPlugin-C1SSNuWp.js → LatexPlugin-DIjHiR2x.js} +7 -7
  121. package/src/ui/dist/assets/{MarkdownViewerPlugin-D2Mf5tU5.js → MarkdownViewerPlugin-D3ooGAH0.js} +4 -4
  122. package/src/ui/dist/assets/{MarketplacePlugin-CF4LgiS2.js → MarketplacePlugin-DfVfE9hN.js} +3 -3
  123. package/src/ui/dist/assets/{NotebookEditor-BM7Bgwlv.js → NotebookEditor-DDl0_Mc0.js} +1 -1
  124. package/src/ui/dist/assets/{index-Be0NAmh8.js → NotebookEditor-s8JhzuX1.js} +12 -155
  125. package/src/ui/dist/assets/{PdfLoader-Bc5qfD-Z.js → PdfLoader-C2Sf6SJM.js} +1 -1
  126. package/src/ui/dist/assets/{PdfMarkdownPlugin-sh1-IRcp.js → PdfMarkdownPlugin-CXFLoIsa.js} +3 -3
  127. package/src/ui/dist/assets/{PdfViewerPlugin-C_a7CpWG.js → PdfViewerPlugin-BYTmz2fK.js} +10 -10
  128. package/src/ui/dist/assets/{SearchPlugin-L4z3HcLf.js → SearchPlugin-CjWBI1O9.js} +1 -1
  129. package/src/ui/dist/assets/{Stepper-Dk4aQ3fN.js → Stepper-B0Dd8CxK.js} +1 -1
  130. package/src/ui/dist/assets/{TextViewerPlugin-BsNtlKVo.js → TextViewerPlugin-DdOBU3-S.js} +4 -4
  131. package/src/ui/dist/assets/{VNCViewer-BpeDcZ5_.js → VNCViewer-B8HGgLwQ.js} +9 -9
  132. package/src/ui/dist/assets/{bibtex-C4QI-bbj.js → bibtex-CKaefIN2.js} +1 -1
  133. package/src/ui/dist/assets/{code-DuMINRsg.js → code-BWAY76JP.js} +1 -1
  134. package/src/ui/dist/assets/{file-content-C3N-432K.js → file-content-C1NwU5oQ.js} +1 -1
  135. package/src/ui/dist/assets/{file-diff-panel-CffQ4ZMg.js → file-diff-panel-CywslwB9.js} +1 -1
  136. package/src/ui/dist/assets/{file-socket-CRH59PCO.js → file-socket-B4kzuOBQ.js} +1 -1
  137. package/src/ui/dist/assets/{file-utils-vYGtW2mI.js → file-utils-H2fjA46S.js} +1 -1
  138. package/src/ui/dist/assets/{image-DBVGaooo.js → image-D-NZM-6P.js} +1 -1
  139. package/src/ui/dist/assets/{index-B1P6hQRJ.js → index-7Chr1g9c.js} +3734 -1862
  140. package/src/ui/dist/assets/{index-DjSFDmgB.js → index-BdM1Gqfr.js} +2 -2
  141. package/src/ui/dist/assets/{index-BpjYH9Vg.js → index-CDxNdQdz.js} +1 -1
  142. package/src/ui/dist/assets/{index-Do9N28uB.css → index-DGIYDuTv.css} +163 -34
  143. package/src/ui/dist/assets/index-DHZJ_0TI.js +159 -0
  144. package/src/ui/dist/assets/{message-square-BsPDBhiY.js → message-square-BzjLiXir.js} +1 -1
  145. package/src/ui/dist/assets/{monaco-BTkdPojV.js → monaco-Cb2uKKe6.js} +1 -1
  146. package/src/ui/dist/assets/{popover-cWjCk-vc.js → popover-Bg72DGgT.js} +1 -1
  147. package/src/ui/dist/assets/{project-sync-CXn530xb.js → project-sync-Ce_0BglY.js} +1 -1
  148. package/src/ui/dist/assets/{sigma-04Jr12jg.js → sigma-DPaACDrh.js} +1 -1
  149. package/src/ui/dist/assets/{tooltip-BdVDl0G5.js → tooltip-C_mA6R0w.js} +1 -1
  150. package/src/ui/dist/assets/{trash-CB_GlQyC.js → trash-BvTgE5__.js} +1 -1
  151. package/src/ui/dist/assets/{useCliAccess-BL932NwS.js → useCliAccess-CgPeMOwP.js} +1 -1
  152. package/src/ui/dist/assets/{useFileDiffOverlay-B2WK7Tvq.js → useFileDiffOverlay-xPhz7P5B.js} +1 -1
  153. package/src/ui/dist/assets/{wrap-text-YC68g12z.js → wrap-text-C3Un3YQr.js} +1 -1
  154. package/src/ui/dist/assets/{zoom-out-C0RJvFiJ.js → zoom-out-BgxLa0Ri.js} +1 -1
  155. package/src/ui/dist/index.html +5 -2
  156. /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
- return service.record_main_experiment(
314
- context.require_quest_root(),
315
- run_id=run_id,
316
- title=title,
317
- hypothesis=hypothesis,
318
- setup=setup,
319
- execution=execution,
320
- results=results,
321
- conclusion=conclusion,
322
- metric_rows=metric_rows,
323
- metrics_summary=metrics_summary,
324
- metric_contract=metric_contract,
325
- evidence_paths=evidence_paths,
326
- changed_files=changed_files,
327
- config_paths=config_paths,
328
- notes=notes,
329
- dataset_scope=dataset_scope,
330
- verdict=verdict,
331
- status=status,
332
- baseline_id=baseline_id,
333
- baseline_variant_id=baseline_variant_id,
334
- evaluation_summary=evaluation_summary,
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",
@@ -357,7 +471,7 @@ def build_artifact_server(context: McpContext) -> FastMCP:
357
471
  context.require_quest_root(),
358
472
  campaign_title=campaign_title,
359
473
  campaign_goal=campaign_goal,
360
- parent_run_id=parent_run_id or context.run_id,
474
+ parent_run_id=parent_run_id,
361
475
  slices=slices,
362
476
  campaign_origin=campaign_origin,
363
477
  selected_outline_ref=selected_outline_ref,
@@ -522,24 +636,30 @@ def build_artifact_server(context: McpContext) -> FastMCP:
522
636
  summary: str | None = None,
523
637
  baseline_kind: str | None = None,
524
638
  metric_contract: dict[str, Any] | None = None,
639
+ metric_directions: dict[str, str] | None = None,
525
640
  metrics_summary: dict[str, Any] | None = None,
526
641
  primary_metric: dict[str, Any] | None = None,
527
642
  auto_advance: bool = True,
528
643
  comment: str | dict[str, Any] | None = None,
529
644
  ) -> dict[str, Any]:
530
- return service.confirm_baseline(
531
- context.require_quest_root(),
532
- baseline_path=baseline_path,
533
- comment=comment,
534
- baseline_id=baseline_id,
535
- variant_id=variant_id,
536
- summary=summary,
537
- baseline_kind=baseline_kind,
538
- metric_contract=metric_contract,
539
- metrics_summary=metrics_summary,
540
- primary_metric=primary_metric,
541
- auto_advance=auto_advance,
542
- )
645
+ try:
646
+ return service.confirm_baseline(
647
+ context.require_quest_root(),
648
+ baseline_path=baseline_path,
649
+ comment=comment,
650
+ baseline_id=baseline_id,
651
+ variant_id=variant_id,
652
+ summary=summary,
653
+ baseline_kind=baseline_kind,
654
+ metric_contract=metric_contract,
655
+ metric_directions=metric_directions,
656
+ metrics_summary=metrics_summary,
657
+ primary_metric=primary_metric,
658
+ auto_advance=auto_advance,
659
+ strict_metric_contract=True,
660
+ )
661
+ except MetricContractValidationError as exc:
662
+ return _metric_validation_error_payload(exc)
543
663
 
544
664
  @server.tool(
545
665
  name="waive_baseline",
@@ -661,7 +781,10 @@ def build_bash_exec_server(context: McpContext) -> FastMCP:
661
781
  description=(
662
782
  "Execute a bash command inside the current quest. "
663
783
  "mode=detach returns immediately. mode=await/create waits for completion. "
664
- "mode=read returns the saved log or a tailed log window. mode=kill requests termination. "
784
+ "mode=read returns the saved log. It returns the full saved log up to 2000 lines, "
785
+ "or a 500-line head plus 1500-line tail preview for longer logs. "
786
+ "Use start/tail for rendered line windows and tail_limit/after_seq for seq-based monitoring. "
787
+ "mode=kill requests termination. "
665
788
  "mode=list shows known quest-local bash sessions. mode=history shows a compact reverse-chronological bash id list."
666
789
  ),
667
790
  )
@@ -681,6 +804,8 @@ def build_bash_exec_server(context: McpContext) -> FastMCP:
681
804
  agent_instance_ids: list[str] | None = None,
682
805
  chat_session_id: str | None = None,
683
806
  limit: int = 20,
807
+ start: int | None = None,
808
+ tail: int | None = None,
684
809
  tail_limit: int | None = None,
685
810
  before_seq: int | None = None,
686
811
  after_seq: int | None = None,
@@ -732,6 +857,29 @@ def build_bash_exec_server(context: McpContext) -> FastMCP:
732
857
  normalized_order = (order or "asc").strip().lower()
733
858
  if normalized_order not in {"asc", "desc"}:
734
859
  normalized_order = "asc"
860
+ if tail is not None and tail_limit is not None:
861
+ raise ValueError("Use either `tail` or `tail_limit`, not both.")
862
+ use_line_window = start is not None or tail is not None or (start is not None and tail_limit is not None)
863
+ if use_line_window and (before_seq is not None or after_seq is not None):
864
+ raise ValueError("`start`/`tail` cannot be combined with `before_seq` or `after_seq`.")
865
+ if use_line_window and normalized_order != "asc":
866
+ raise ValueError("`start`/`tail` windows only support `order='asc'`.")
867
+ if use_line_window:
868
+ payload = service.build_tool_result(
869
+ context,
870
+ session=session,
871
+ include_log=False,
872
+ export_log=export_log,
873
+ export_log_to=export_log_to,
874
+ )
875
+ payload.update(
876
+ _build_bash_log_window(
877
+ service.read_terminal_log(quest_root, bash_id),
878
+ start=start,
879
+ tail=tail if tail is not None else tail_limit,
880
+ )
881
+ )
882
+ return payload
735
883
  use_tail = tail_limit is not None or before_seq is not None or after_seq is not None or normalized_order != "asc"
736
884
  if use_tail:
737
885
  resolved_tail_limit = max(1, min(int(tail_limit or 200), 1000))
@@ -742,6 +890,7 @@ def build_bash_exec_server(context: McpContext) -> FastMCP:
742
890
  before_seq=before_seq,
743
891
  after_seq=after_seq,
744
892
  order=normalized_order,
893
+ prefer_visible=True,
745
894
  )
746
895
  payload = service.build_tool_result(
747
896
  context,
@@ -758,13 +907,15 @@ def build_bash_exec_server(context: McpContext) -> FastMCP:
758
907
  payload["before_seq"] = tail_meta.get("before_seq")
759
908
  payload["order"] = normalized_order
760
909
  return payload
761
- return service.build_tool_result(
910
+ payload = service.build_tool_result(
762
911
  context,
763
912
  session=session,
764
- include_log=True,
913
+ include_log=False,
765
914
  export_log=export_log,
766
915
  export_log_to=export_log_to,
767
916
  )
917
+ payload.update(_build_default_bash_log_payload(service.read_terminal_log(quest_root, bash_id)))
918
+ return payload
768
919
  if normalized_mode == "kill":
769
920
  bash_id = service.resolve_session_id(quest_root, id)
770
921
  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}",
@@ -681,6 +687,8 @@ class PromptBuilder:
681
687
  f"- delivery_mode: {'paper_required' if need_research_paper else 'algorithm_first'}",
682
688
  "- idea_stage_rule: every accepted idea submission should normally create a new branch/worktree and a new user-visible research node.",
683
689
  "- idea_draft_rule: before `artifact.submit_idea(...)`, first finish a concise durable Markdown draft for the chosen route; keep `idea.md` compact and `draft.md` richer.",
690
+ "- idea_literature_floor_rule: before writing or submitting a final selected idea, durably survey at least 5 and usually 5 to 10 related and usable papers; prioritize direct task-modeling or mechanism-neighbor work and only backfill with the closest adjacent translatable papers when necessary.",
691
+ "- idea_reference_rule: the final selected-idea draft should use one consistent standard citation format and include a `References` or `Bibliography` section for the survey-stage papers that actually shaped the motivation, mechanism, or claim boundary.",
684
692
  "- lineage_rule: normal idea routing uses exactly two lineage intents: `continue_line` creates a child of the current active branch; `branch_alternative` creates a sibling-like branch from the current branch's parent foundation.",
685
693
  "- revise_rule: `artifact.submit_idea(mode='revise', ...)` is maintenance-only compatibility for the same branch and should not be the default research-route mechanism.",
686
694
  "- post_main_result_rule: after every `artifact.record_main_experiment(...)`, first interpret the measured result and only then choose the next route.",
@@ -718,6 +726,11 @@ class PromptBuilder:
718
726
  [
719
727
  "- delivery_goal: the quest should normally continue until at least one paper-like deliverable exists.",
720
728
  "- main_result_rule: a strong main experiment is evidence, not the endpoint; usually continue into the necessary analysis, writing, or further strengthening work.",
729
+ "- 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.",
730
+ "- 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.",
731
+ "- 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.",
732
+ "- 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.",
733
+ "- 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
734
  "- writing_rule: when the evidence becomes strong enough, analysis and paper writing remain in scope by default.",
722
735
  "- 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
736
  "- stop_rule: do not stop with only an improved algorithm or isolated run logs unless the user explicitly narrows scope.",
@@ -755,15 +768,17 @@ class PromptBuilder:
755
768
  "- 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
769
  "- 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
770
  "- 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, send a concise keepalive before you drift beyond roughly 10 to 30 tool calls without a user-visible update",
771
+ "- 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
772
  "- 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
773
  "- 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
774
  "- 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",
775
+ "- 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
776
  "- 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
777
  "- 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
778
  "- 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
- "- tail_monitoring_protocol: when monitoring a detached run, prefer bash_exec(mode='read', id=..., tail_limit=..., order='desc') so you inspect the newest evidence first instead of re-reading full logs every time",
779
+ "- 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",
780
+ "- 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",
781
+ "- 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
782
  "- 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
783
  "- 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
784
  "- blocking_protocol: use reply_mode='blocking' only for true unresolved user decisions; ordinary progress updates should stay threaded and non-blocking",
@@ -774,8 +789,9 @@ class PromptBuilder:
774
789
  "- 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
790
  "- 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
791
  "- 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, if you have spent roughly 10 to 30 tool calls without a user-visible checkpoint, send one concise artifact.interact progress update before continuing",
792
+ "- 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
793
  "- 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",
794
+ "- 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
795
  "- 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
796
  "- 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
797
  "- 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 +799,7 @@ class PromptBuilder:
783
799
  "- 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
800
  "- 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
801
  "- plan_revision_protocol: if the route, comparability contract, source package, execution strategy, slice ordering, or campaign interpretation changes materially, revise `PLAN.md` before continuing",
802
+ "- 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
803
  "- 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
804
  "- 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
805
  "- 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",
@@ -791,7 +808,11 @@ class PromptBuilder:
791
808
  "- idea_why_now_protocol: every serious idea candidate should answer why now or what changed, not just what the mechanism is",
792
809
  "- 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
810
  "- 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",
811
+ "- idea_literature_floor_protocol: do not write or submit the final selected idea until the durable survey covers at least 5 and usually 5 to 10 related and usable papers; if fewer than 5 direct papers exist, document the shortage and use the closest adjacent translatable work instead of skipping the gate",
812
+ "- idea_reference_protocol: the final selected-idea draft should cite the survey-stage papers it actually uses and end with a standard-format `References` or `Bibliography` section",
794
813
  "- 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",
814
+ "- 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",
815
+ "- 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
816
  "- 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
817
  "- 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
818
  "- explicit_improvement_protocol: never make the user infer performance improvement only from raw metrics; say plainly whether performance improved, worsened, or stayed mixed",
@@ -935,7 +956,16 @@ class PromptBuilder:
935
956
  attachment_root = active_workspace_root / "baselines" / "imported"
936
957
  if attachment_root.exists():
937
958
  attachments = [read_yaml(path, {}) for path in sorted(attachment_root.glob("*/attachment.yaml"))]
938
- attachments = [item for item in attachments if isinstance(item, dict) and item]
959
+ attachments = [
960
+ item
961
+ for item in attachments
962
+ if isinstance(item, dict)
963
+ and item
964
+ and (
965
+ not str(item.get("source_baseline_id") or "").strip()
966
+ or not self.baseline_registry.is_deleted(str(item.get("source_baseline_id") or "").strip())
967
+ )
968
+ ]
939
969
  if attachments:
940
970
  attachment = max(
941
971
  attachments,
@@ -1076,7 +1106,13 @@ class PromptBuilder:
1076
1106
  return "\n".join(lines)
1077
1107
 
1078
1108
  def _paper_and_evidence_block(self, snapshot: dict, quest_root: Path) -> str:
1079
- paper_root = quest_root / "paper"
1109
+ workspace_root = Path(str(snapshot.get("active_workspace_root") or quest_root))
1110
+ paper_root = workspace_root / "paper"
1111
+ if not paper_root.exists():
1112
+ paper_root = quest_root / "paper"
1113
+ open_source_root = workspace_root / "release" / "open_source"
1114
+ if not open_source_root.exists():
1115
+ open_source_root = quest_root / "release" / "open_source"
1080
1116
  selected_outline = read_json(paper_root / "selected_outline.json", {})
1081
1117
  selected_outline = selected_outline if isinstance(selected_outline, dict) else {}
1082
1118
  detailed_outline = (
@@ -1092,8 +1128,18 @@ class PromptBuilder:
1092
1128
  claim_evidence_map = claim_evidence_map if isinstance(claim_evidence_map, dict) else {}
1093
1129
  compile_report = read_json(paper_root / "build" / "compile_report.json", {})
1094
1130
  compile_report = compile_report if isinstance(compile_report, dict) else {}
1095
- open_source_manifest = read_json(quest_root / "release" / "open_source" / "manifest.json", {})
1131
+ open_source_manifest = read_json(open_source_root / "manifest.json", {})
1096
1132
  open_source_manifest = open_source_manifest if isinstance(open_source_manifest, dict) else {}
1133
+ default_paper_prefix = (
1134
+ paper_root.relative_to(quest_root).as_posix()
1135
+ if paper_root.is_relative_to(quest_root)
1136
+ else "paper"
1137
+ )
1138
+ default_release_prefix = (
1139
+ open_source_root.relative_to(quest_root).as_posix()
1140
+ if open_source_root.is_relative_to(quest_root)
1141
+ else "release/open_source"
1142
+ )
1097
1143
 
1098
1144
  selected_outline_ref = str(
1099
1145
  selected_outline.get("outline_id") or bundle_manifest.get("selected_outline_ref") or ""
@@ -1130,14 +1176,14 @@ class PromptBuilder:
1130
1176
 
1131
1177
  lines.extend(
1132
1178
  [
1133
- f"- writing_plan_status: {_path_status(bundle_manifest.get('writing_plan_path'), fallback='paper/writing_plan.md')}",
1134
- f"- draft_status: {_path_status(bundle_manifest.get('draft_path'), fallback='paper/draft.md')}",
1135
- f"- references_status: {_path_status(bundle_manifest.get('references_path'), fallback='paper/references.bib')}",
1136
- f"- claim_evidence_map_status: {_path_status(bundle_manifest.get('claim_evidence_map_path'), fallback='paper/claim_evidence_map.json')}",
1137
- f"- baseline_inventory_status: {_path_status(bundle_manifest.get('baseline_inventory_path'), fallback='paper/baseline_inventory.json')}",
1138
- f"- review_status: {'paper/review/review.md [exists]' if (paper_root / 'review' / 'review.md').exists() else 'paper/review/review.md [missing]'}",
1139
- f"- proofing_report_status: {'paper/proofing/proofing_report.md [exists]' if (paper_root / 'proofing' / 'proofing_report.md').exists() else 'paper/proofing/proofing_report.md [missing]'}",
1140
- f"- page_images_manifest_status: {'paper/proofing/page_images_manifest.json [exists]' if (paper_root / 'proofing' / 'page_images_manifest.json').exists() else 'paper/proofing/page_images_manifest.json [missing]'}",
1179
+ f"- writing_plan_status: {_path_status(bundle_manifest.get('writing_plan_path'), fallback=f'{default_paper_prefix}/writing_plan.md')}",
1180
+ f"- draft_status: {_path_status(bundle_manifest.get('draft_path'), fallback=f'{default_paper_prefix}/draft.md')}",
1181
+ f"- references_status: {_path_status(bundle_manifest.get('references_path'), fallback=f'{default_paper_prefix}/references.bib')}",
1182
+ f"- claim_evidence_map_status: {_path_status(bundle_manifest.get('claim_evidence_map_path'), fallback=f'{default_paper_prefix}/claim_evidence_map.json')}",
1183
+ f"- baseline_inventory_status: {_path_status(bundle_manifest.get('baseline_inventory_path'), fallback=f'{default_paper_prefix}/baseline_inventory.json')}",
1184
+ 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]'}",
1185
+ 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]'}",
1186
+ 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
1187
  ]
1142
1188
  )
1143
1189
 
@@ -1148,11 +1194,11 @@ class PromptBuilder:
1148
1194
  lines.extend(
1149
1195
  [
1150
1196
  "- paper_bundle_manifest_present: True",
1151
- f"- bundle_pdf_status: {_path_status(pdf_rel_path, fallback='paper/paper.pdf')}",
1152
- f"- bundle_compile_report_status: {_path_status(compile_rel_path, fallback='paper/build/compile_report.json')}",
1197
+ f"- bundle_pdf_status: {_path_status(pdf_rel_path, fallback=f'{default_paper_prefix}/paper.pdf')}",
1198
+ f"- bundle_compile_report_status: {_path_status(compile_rel_path, fallback=f'{default_paper_prefix}/build/compile_report.json')}",
1153
1199
  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='release/open_source/manifest.json')}",
1155
- f"- open_source_cleanup_plan_status: {_path_status(bundle_manifest.get('open_source_cleanup_plan_path'), fallback='release/open_source/cleanup_plan.md')}",
1200
+ f"- open_source_manifest_status: {_path_status(bundle_manifest.get('open_source_manifest_path'), fallback=f'{default_release_prefix}/manifest.json')}",
1201
+ 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
1202
  ]
1157
1203
  )
1158
1204
  else: