@researai/deepscientist 1.5.8 → 1.5.11
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/LICENSE +186 -21
- package/README.md +108 -95
- package/assets/branding/connector-qq.png +0 -0
- package/assets/branding/connector-rokid.png +0 -0
- package/assets/branding/connector-weixin.png +0 -0
- package/assets/branding/projects.png +0 -0
- package/bin/ds.js +172 -13
- package/docs/assets/branding/projects.png +0 -0
- package/docs/en/00_QUICK_START.md +308 -70
- package/docs/en/01_SETTINGS_REFERENCE.md +3 -0
- package/docs/en/02_START_RESEARCH_GUIDE.md +112 -0
- package/docs/en/04_LINGZHU_CONNECTOR_GUIDE.md +62 -179
- package/docs/en/09_DOCTOR.md +41 -5
- package/docs/en/10_WEIXIN_CONNECTOR_GUIDE.md +137 -0
- package/docs/en/11_LICENSE_AND_RISK.md +256 -0
- package/docs/en/12_GUIDED_WORKFLOW_TOUR.md +427 -0
- package/docs/en/13_CORE_ARCHITECTURE_GUIDE.md +297 -0
- package/docs/en/14_PROMPT_SKILLS_AND_MCP_GUIDE.md +506 -0
- package/docs/en/99_ACKNOWLEDGEMENTS.md +4 -1
- package/docs/en/README.md +79 -0
- package/docs/images/lingzhu/rokid-agent-platform-create.png +0 -0
- package/docs/images/weixin/weixin-plugin-entry.png +0 -0
- package/docs/images/weixin/weixin-plugin-entry.svg +33 -0
- package/docs/images/weixin/weixin-qr-confirm.svg +30 -0
- package/docs/images/weixin/weixin-quest-media-flow.svg +44 -0
- package/docs/images/weixin/weixin-settings-bind.svg +57 -0
- package/docs/zh/00_QUICK_START.md +315 -74
- package/docs/zh/01_SETTINGS_REFERENCE.md +3 -0
- package/docs/zh/02_START_RESEARCH_GUIDE.md +112 -0
- package/docs/zh/04_LINGZHU_CONNECTOR_GUIDE.md +62 -193
- package/docs/zh/09_DOCTOR.md +41 -5
- package/docs/zh/10_WEIXIN_CONNECTOR_GUIDE.md +144 -0
- package/docs/zh/11_LICENSE_AND_RISK.md +256 -0
- package/docs/zh/12_GUIDED_WORKFLOW_TOUR.md +423 -0
- package/docs/zh/13_CORE_ARCHITECTURE_GUIDE.md +296 -0
- package/docs/zh/14_PROMPT_SKILLS_AND_MCP_GUIDE.md +506 -0
- package/docs/zh/99_ACKNOWLEDGEMENTS.md +4 -1
- package/docs/zh/README.md +126 -0
- package/install.sh +0 -34
- package/package.json +3 -3
- package/pyproject.toml +2 -2
- package/src/deepscientist/__init__.py +1 -1
- package/src/deepscientist/annotations.py +343 -0
- package/src/deepscientist/artifact/arxiv.py +484 -37
- package/src/deepscientist/artifact/metrics.py +1 -3
- package/src/deepscientist/artifact/service.py +1347 -111
- package/src/deepscientist/arxiv_library.py +275 -0
- package/src/deepscientist/bash_exec/service.py +9 -0
- package/src/deepscientist/bridges/builtins.py +2 -0
- package/src/deepscientist/bridges/connectors.py +447 -0
- package/src/deepscientist/channels/__init__.py +2 -0
- package/src/deepscientist/channels/builtins.py +3 -1
- package/src/deepscientist/channels/qq.py +1 -1
- package/src/deepscientist/channels/qq_gateway.py +1 -1
- package/src/deepscientist/channels/relay.py +7 -1
- package/src/deepscientist/channels/weixin.py +59 -0
- package/src/deepscientist/channels/weixin_ilink.py +317 -0
- package/src/deepscientist/config/models.py +22 -2
- package/src/deepscientist/config/service.py +431 -60
- package/src/deepscientist/connector/__init__.py +4 -0
- package/src/deepscientist/connector/connector_profiles.py +481 -0
- package/src/deepscientist/connector/lingzhu_support.py +668 -0
- package/src/deepscientist/connector/qq_profiles.py +206 -0
- package/src/deepscientist/connector/weixin_support.py +663 -0
- package/src/deepscientist/connector_profiles.py +1 -374
- package/src/deepscientist/connector_runtime.py +2 -0
- package/src/deepscientist/daemon/api/handlers.py +295 -5
- package/src/deepscientist/daemon/api/router.py +16 -1
- package/src/deepscientist/daemon/app.py +1130 -61
- package/src/deepscientist/doctor.py +5 -2
- package/src/deepscientist/gitops/diff.py +120 -29
- package/src/deepscientist/lingzhu_support.py +1 -182
- package/src/deepscientist/mcp/server.py +14 -5
- package/src/deepscientist/prompts/builder.py +29 -1
- package/src/deepscientist/qq_profiles.py +1 -196
- package/src/deepscientist/quest/node_traces.py +152 -2
- package/src/deepscientist/quest/service.py +169 -43
- package/src/deepscientist/quest/stage_views.py +172 -9
- package/src/deepscientist/registries/baseline.py +56 -4
- package/src/deepscientist/runners/codex.py +55 -3
- package/src/deepscientist/weixin_support.py +1 -0
- package/src/prompts/connectors/lingzhu.md +3 -1
- package/src/prompts/connectors/weixin.md +230 -0
- package/src/prompts/system.md +9 -0
- package/src/skills/idea/SKILL.md +16 -0
- package/src/skills/idea/references/literature-survey-template.md +24 -0
- package/src/skills/idea/references/related-work-playbook.md +4 -0
- package/src/skills/idea/references/selection-gate.md +9 -0
- package/src/skills/write/SKILL.md +1 -1
- package/src/tui/package.json +1 -1
- package/src/ui/dist/assets/{AiManusChatView-m2FNtwbn.js → AiManusChatView-D0mTXG4-.js} +156 -48
- package/src/ui/dist/assets/{AnalysisPlugin-BMTF8EGL.js → AnalysisPlugin-Db0cTXxm.js} +1 -1
- package/src/ui/dist/assets/{CliPlugin-BEOWgxCI.js → CliPlugin-DrV8je02.js} +164 -9
- package/src/ui/dist/assets/{CodeEditorPlugin-BCXvjqmb.js → CodeEditorPlugin-QXMSCH71.js} +8 -8
- package/src/ui/dist/assets/{CodeViewerPlugin-DaJcy3nD.js → CodeViewerPlugin-7hhtWj_E.js} +5 -5
- package/src/ui/dist/assets/{DocViewerPlugin-ByfeIq4K.js → DocViewerPlugin-BWMSnRJe.js} +3 -3
- package/src/ui/dist/assets/{GitDiffViewerPlugin-Cksf3VZ-.js → GitDiffViewerPlugin-7J9h9Vy_.js} +20 -21
- package/src/ui/dist/assets/{ImageViewerPlugin-CFz-OsTS.js → ImageViewerPlugin-CHJl_0lr.js} +5 -5
- package/src/ui/dist/assets/{LabCopilotPanel-CJ1cJzoX.js → LabCopilotPanel-1qSow1es.js} +11 -11
- package/src/ui/dist/assets/{LabPlugin-BF3dVJwa.js → LabPlugin-eQpPPCEp.js} +2 -1
- package/src/ui/dist/assets/{LatexPlugin-DDkwZ6Sj.js → LatexPlugin-BwRfi89Z.js} +7 -7
- package/src/ui/dist/assets/{MarkdownViewerPlugin-HAuvurcT.js → MarkdownViewerPlugin-836PVQWV.js} +4 -4
- package/src/ui/dist/assets/{MarketplacePlugin-BtoTYy2C.js → MarketplacePlugin-C2y_556i.js} +3 -3
- package/src/ui/dist/assets/{NotebookEditor-CSJYx7b-.js → NotebookEditor-BRzJbGsn.js} +12 -12
- package/src/ui/dist/assets/{NotebookEditor-DQgRezm_.js → NotebookEditor-DIX7Mlzu.js} +1 -1
- package/src/ui/dist/assets/{PdfLoader-DPa_-fv6.js → PdfLoader-DzRaTAlq.js} +14 -7
- package/src/ui/dist/assets/{PdfMarkdownPlugin-BZpXOEjm.js → PdfMarkdownPlugin-DZUfIUnp.js} +73 -6
- package/src/ui/dist/assets/{PdfViewerPlugin-BT8a6wGR.js → PdfViewerPlugin-BwtICzue.js} +103 -34
- package/src/ui/dist/assets/PdfViewerPlugin-DQ11QcSf.css +3627 -0
- package/src/ui/dist/assets/{SearchPlugin-D_blveZi.js → SearchPlugin-DHeIAMsx.js} +1 -1
- package/src/ui/dist/assets/{TextViewerPlugin-Btx0M3hX.js → TextViewerPlugin-C3tCmFox.js} +5 -4
- package/src/ui/dist/assets/{VNCViewer-DImJO4rO.js → VNCViewer-CQsKVm3t.js} +10 -10
- package/src/ui/dist/assets/bot-BEA2vWuK.js +21 -0
- package/src/ui/dist/assets/branding/logo-rokid.png +0 -0
- package/src/ui/dist/assets/browser-BAcuE0Xj.js +2895 -0
- package/src/ui/dist/assets/{code-BUfXGJSl.js → code-XfbSR8K2.js} +1 -1
- package/src/ui/dist/assets/{file-content-VqamwI3X.js → file-content-BjxNaIfy.js} +1 -1
- package/src/ui/dist/assets/{file-diff-panel-C_wOoS7a.js → file-diff-panel-D_lLVQk0.js} +1 -1
- package/src/ui/dist/assets/{file-socket-D2bTuMVP.js → file-socket-D9x_5vlY.js} +1 -1
- package/src/ui/dist/assets/{image-BZkGJ4mM.js → image-BhWT33W1.js} +1 -1
- package/src/ui/dist/assets/{index-DdRW6RMJ.js → index--c4iXtuy.js} +12 -12
- package/src/ui/dist/assets/{index-CxkvSeKw.js → index-BDxipwrC.js} +2 -2
- package/src/ui/dist/assets/{index-DjggJovS.js → index-DZTZ8mWP.js} +14934 -9613
- package/src/ui/dist/assets/{index-DXZ1daiJ.css → index-Dqj-Mjb4.css} +2 -13
- package/src/ui/dist/assets/index-PJbSbPTy.js +25 -0
- package/src/ui/dist/assets/{monaco-DHMc7kKM.js → monaco-K8izTGgo.js} +1 -1
- package/src/ui/dist/assets/{pdf-effect-queue-DSw_D3RV.js → pdf-effect-queue-DfBors6y.js} +16 -1
- package/src/ui/dist/assets/pdf.worker.min-yatZIOMy.mjs +21 -0
- package/src/ui/dist/assets/{popover-B85oCgCS.js → popover-yFK1J4fL.js} +1 -1
- package/src/ui/dist/assets/{project-sync-DOMCcPac.js → project-sync-PENr2zcz.js} +1 -74
- package/src/ui/dist/assets/select-CAbJDfYv.js +1690 -0
- package/src/ui/dist/assets/{sigma-BO2rQrl3.js → sigma-DEuYJqTl.js} +1 -1
- package/src/ui/dist/assets/{index-D9QIGcmc.js → square-check-big-omoSUmcd.js} +2 -13
- package/src/ui/dist/assets/{trash-BsVEH_dV.js → trash--F119N47.js} +1 -1
- package/src/ui/dist/assets/{useCliAccess-b8L6JuZm.js → useCliAccess-D31UR23I.js} +1 -1
- package/src/ui/dist/assets/{useFileDiffOverlay-BY7uA9hV.js → useFileDiffOverlay-BH6KcMzq.js} +1 -1
- package/src/ui/dist/assets/{wrap-text-BwyVuUIK.js → wrap-text-CZ613PM5.js} +1 -1
- package/src/ui/dist/assets/{zoom-out-RDpLugQP.js → zoom-out-BgDLAv3z.js} +1 -1
- package/src/ui/dist/index.html +2 -2
- package/src/ui/dist/assets/AutoFigurePlugin-BGxN8Umr.css +0 -3056
- package/src/ui/dist/assets/AutoFigurePlugin-DxPdMUNb.js +0 -8149
- package/src/ui/dist/assets/PdfViewerPlugin-BJXtIwj_.css +0 -260
- package/src/ui/dist/assets/Stepper-DH2k75Vo.js +0 -158
- package/src/ui/dist/assets/bibtex-B-Hqu0Sg.js +0 -189
- package/src/ui/dist/assets/file-utils--zJCPN1i.js +0 -109
- package/src/ui/dist/assets/message-square-FUIPIhU2.js +0 -16
- package/src/ui/dist/assets/pdfjs-DU1YE8WO.js +0 -3
- package/src/ui/dist/assets/tooltip-B1OspAkx.js +0 -108
|
@@ -22,26 +22,49 @@ class BaselineRegistry:
|
|
|
22
22
|
self.reconcile_confirmed_quests()
|
|
23
23
|
entry_files = sorted(self.entries_root.glob("*.yaml"))
|
|
24
24
|
if entry_files:
|
|
25
|
-
return sorted(
|
|
25
|
+
return sorted(
|
|
26
|
+
(
|
|
27
|
+
entry
|
|
28
|
+
for path in entry_files
|
|
29
|
+
for entry in [self._load_entry_file(path)]
|
|
30
|
+
if not self._is_deleted_entry(entry)
|
|
31
|
+
),
|
|
32
|
+
key=self._entry_sort_key,
|
|
33
|
+
)
|
|
26
34
|
|
|
27
35
|
latest_by_id: dict[str, dict] = {}
|
|
28
36
|
for item in self._history_entries():
|
|
29
37
|
baseline_id = str(item.get("baseline_id") or item.get("entry_id") or "").strip()
|
|
30
38
|
if baseline_id:
|
|
31
39
|
latest_by_id[baseline_id] = item
|
|
32
|
-
return sorted(
|
|
40
|
+
return sorted(
|
|
41
|
+
(item for item in latest_by_id.values() if not self._is_deleted_entry(item)),
|
|
42
|
+
key=self._entry_sort_key,
|
|
43
|
+
)
|
|
33
44
|
|
|
34
|
-
def get(self, baseline_id: str) -> dict | None:
|
|
45
|
+
def get(self, baseline_id: str, *, include_deleted: bool = False) -> dict | None:
|
|
35
46
|
normalized_id = self._normalize_identifier(baseline_id, field_name="Baseline id")
|
|
36
47
|
path = self._entry_path(normalized_id)
|
|
37
48
|
if path.exists():
|
|
38
|
-
|
|
49
|
+
entry = self._load_entry_file(path)
|
|
50
|
+
if self._is_deleted_entry(entry) and not include_deleted:
|
|
51
|
+
return None
|
|
52
|
+
return entry
|
|
39
53
|
latest_match = None
|
|
40
54
|
for item in self._history_entries():
|
|
41
55
|
if item.get("baseline_id") == normalized_id or item.get("entry_id") == normalized_id:
|
|
42
56
|
latest_match = item
|
|
57
|
+
if self._is_deleted_entry(latest_match) and not include_deleted:
|
|
58
|
+
return None
|
|
43
59
|
return latest_match
|
|
44
60
|
|
|
61
|
+
def is_deleted(self, baseline_id: str) -> bool:
|
|
62
|
+
try:
|
|
63
|
+
entry = self.get(baseline_id, include_deleted=True)
|
|
64
|
+
except ValueError:
|
|
65
|
+
return False
|
|
66
|
+
return self._is_deleted_entry(entry)
|
|
67
|
+
|
|
45
68
|
def publish(self, entry: dict) -> dict:
|
|
46
69
|
timestamp = utc_now()
|
|
47
70
|
baseline_id = self._normalize_identifier(
|
|
@@ -201,6 +224,8 @@ class BaselineRegistry:
|
|
|
201
224
|
}
|
|
202
225
|
|
|
203
226
|
existing = self._existing_entry(baseline_id)
|
|
227
|
+
if self._is_deleted_entry(existing):
|
|
228
|
+
continue
|
|
204
229
|
if self._entry_needs_publish(existing, entry):
|
|
205
230
|
synchronized.append(self.publish(entry))
|
|
206
231
|
elif existing:
|
|
@@ -244,6 +269,27 @@ class BaselineRegistry:
|
|
|
244
269
|
write_yaml(attachment_root / "attachment.yaml", attachment)
|
|
245
270
|
return attachment
|
|
246
271
|
|
|
272
|
+
def delete(self, baseline_id: str) -> dict:
|
|
273
|
+
normalized_id = self._normalize_identifier(baseline_id, field_name="Baseline id")
|
|
274
|
+
existing = self.get(normalized_id, include_deleted=True) or {}
|
|
275
|
+
timestamp = utc_now()
|
|
276
|
+
deleted_entry = {
|
|
277
|
+
**existing,
|
|
278
|
+
"registry_kind": "baseline",
|
|
279
|
+
"schema_version": 1,
|
|
280
|
+
"entry_id": normalized_id,
|
|
281
|
+
"baseline_id": normalized_id,
|
|
282
|
+
"status": "deleted",
|
|
283
|
+
"updated_at": timestamp,
|
|
284
|
+
"deleted_at": timestamp,
|
|
285
|
+
"summary": str(existing.get("summary") or "").strip(),
|
|
286
|
+
}
|
|
287
|
+
if not deleted_entry.get("created_at"):
|
|
288
|
+
deleted_entry["created_at"] = timestamp
|
|
289
|
+
write_yaml(self._entry_path(normalized_id), deleted_entry)
|
|
290
|
+
append_jsonl(self.index_path, deleted_entry)
|
|
291
|
+
return deleted_entry
|
|
292
|
+
|
|
247
293
|
def _history_entries(self) -> list[dict]:
|
|
248
294
|
return read_jsonl(self.index_path)
|
|
249
295
|
|
|
@@ -292,6 +338,12 @@ class BaselineRegistry:
|
|
|
292
338
|
entry = self._load_entry_file(path)
|
|
293
339
|
return entry if isinstance(entry, dict) and entry else None
|
|
294
340
|
|
|
341
|
+
@staticmethod
|
|
342
|
+
def _is_deleted_entry(entry: dict[str, Any] | None) -> bool:
|
|
343
|
+
if not isinstance(entry, dict):
|
|
344
|
+
return False
|
|
345
|
+
return str(entry.get("status") or "").strip().lower() == "deleted"
|
|
346
|
+
|
|
295
347
|
@staticmethod
|
|
296
348
|
def _entry_needs_publish(existing: dict[str, Any] | None, candidate: dict[str, Any]) -> bool:
|
|
297
349
|
if not existing:
|
|
@@ -35,6 +35,17 @@ def _compact_text(value: object, *, limit: int = 1200) -> str:
|
|
|
35
35
|
return text[: limit - 1].rstrip() + "…"
|
|
36
36
|
|
|
37
37
|
|
|
38
|
+
def _structured_text(value: object) -> str:
|
|
39
|
+
if value is None:
|
|
40
|
+
return ""
|
|
41
|
+
if isinstance(value, str):
|
|
42
|
+
return value.strip()
|
|
43
|
+
try:
|
|
44
|
+
return json.dumps(value, ensure_ascii=False, indent=2)
|
|
45
|
+
except TypeError:
|
|
46
|
+
return str(value)
|
|
47
|
+
|
|
48
|
+
|
|
38
49
|
def _iter_event_texts(event: dict[str, Any]) -> list[str]:
|
|
39
50
|
texts: list[str] = []
|
|
40
51
|
for key in ("text", "content", "message"):
|
|
@@ -184,7 +195,24 @@ def _tool_name(event: dict[str, Any], item: dict[str, Any]) -> str:
|
|
|
184
195
|
return "tool"
|
|
185
196
|
|
|
186
197
|
|
|
198
|
+
def _is_bash_exec_item(event: dict[str, Any], item: dict[str, Any]) -> bool:
|
|
199
|
+
server = str(item.get("server") or event.get("server") or "").strip()
|
|
200
|
+
tool = str(item.get("tool") or event.get("tool") or "").strip()
|
|
201
|
+
return server == "bash_exec" and tool == "bash_exec"
|
|
202
|
+
|
|
203
|
+
|
|
187
204
|
def _tool_args(event: dict[str, Any], item: dict[str, Any]) -> str:
|
|
205
|
+
if _is_bash_exec_item(event, item):
|
|
206
|
+
for value in (
|
|
207
|
+
item.get("arguments"),
|
|
208
|
+
event.get("arguments"),
|
|
209
|
+
item.get("input"),
|
|
210
|
+
event.get("input"),
|
|
211
|
+
):
|
|
212
|
+
text = _structured_text(value)
|
|
213
|
+
if text:
|
|
214
|
+
return text
|
|
215
|
+
return ""
|
|
188
216
|
for value in (
|
|
189
217
|
item.get("command"),
|
|
190
218
|
item.get("query"),
|
|
@@ -204,6 +232,21 @@ def _tool_args(event: dict[str, Any], item: dict[str, Any]) -> str:
|
|
|
204
232
|
|
|
205
233
|
|
|
206
234
|
def _tool_output(event: dict[str, Any], item: dict[str, Any]) -> str:
|
|
235
|
+
if _is_bash_exec_item(event, item):
|
|
236
|
+
for value in (
|
|
237
|
+
item.get("result"),
|
|
238
|
+
item.get("output"),
|
|
239
|
+
item.get("content"),
|
|
240
|
+
event.get("result"),
|
|
241
|
+
event.get("output"),
|
|
242
|
+
event.get("content"),
|
|
243
|
+
item.get("aggregated_output"),
|
|
244
|
+
event.get("aggregated_output"),
|
|
245
|
+
):
|
|
246
|
+
text = _structured_text(value)
|
|
247
|
+
if text:
|
|
248
|
+
return text
|
|
249
|
+
return ""
|
|
207
250
|
for value in (
|
|
208
251
|
item.get("aggregated_output"),
|
|
209
252
|
item.get("changes"),
|
|
@@ -253,10 +296,12 @@ def _mcp_tool_metadata(
|
|
|
253
296
|
metadata["workdir"] = arguments.get("workdir")
|
|
254
297
|
if isinstance(arguments.get("mode"), str):
|
|
255
298
|
metadata["mode"] = arguments.get("mode")
|
|
256
|
-
if
|
|
299
|
+
if arguments.get("timeout_seconds") is not None:
|
|
257
300
|
metadata["timeout_seconds"] = arguments.get("timeout_seconds")
|
|
258
301
|
if "comment" in arguments:
|
|
259
302
|
metadata["comment"] = arguments.get("comment")
|
|
303
|
+
if server == "bash_exec" and tool == "bash_exec" and isinstance(arguments.get("id"), str):
|
|
304
|
+
metadata["bash_id"] = arguments.get("id")
|
|
260
305
|
metadata["session_id"] = f"quest:{quest_id}"
|
|
261
306
|
metadata["agent_id"] = "pi"
|
|
262
307
|
metadata["agent_instance_id"] = run_id
|
|
@@ -266,12 +311,18 @@ def _mcp_tool_metadata(
|
|
|
266
311
|
for key in (
|
|
267
312
|
"bash_id",
|
|
268
313
|
"status",
|
|
314
|
+
"command",
|
|
315
|
+
"workdir",
|
|
316
|
+
"cwd",
|
|
317
|
+
"kind",
|
|
318
|
+
"comment",
|
|
269
319
|
"started_at",
|
|
270
320
|
"finished_at",
|
|
271
321
|
"exit_code",
|
|
272
322
|
"stop_reason",
|
|
273
323
|
"last_progress",
|
|
274
324
|
"log_path",
|
|
325
|
+
"watchdog_after_seconds",
|
|
275
326
|
):
|
|
276
327
|
if key in result_payload:
|
|
277
328
|
metadata[key] = result_payload.get(key)
|
|
@@ -758,6 +809,7 @@ class CodexRunner:
|
|
|
758
809
|
workspace_root = request.worktree_root or request.quest_root
|
|
759
810
|
resolved_binary = resolve_runner_binary(self.binary, runner_name="codex")
|
|
760
811
|
resolved_runner_config = runner_config if isinstance(runner_config, dict) else self._load_runner_config()
|
|
812
|
+
normalized_model = str(request.model or "").strip()
|
|
761
813
|
command = [
|
|
762
814
|
resolved_binary or self.binary,
|
|
763
815
|
"--search",
|
|
@@ -766,9 +818,9 @@ class CodexRunner:
|
|
|
766
818
|
"--cd",
|
|
767
819
|
str(workspace_root),
|
|
768
820
|
"--skip-git-repo-check",
|
|
769
|
-
"--model",
|
|
770
|
-
request.model,
|
|
771
821
|
]
|
|
822
|
+
if normalized_model.lower() not in {"", "inherit", "default", "codex-default"}:
|
|
823
|
+
command.extend(["--model", normalized_model])
|
|
772
824
|
if request.approval_policy:
|
|
773
825
|
command.extend(["-c", f'approval_policy="{request.approval_policy}"'])
|
|
774
826
|
reasoning_effort = request.reasoning_effort
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .connector.weixin_support import * # noqa: F401,F403
|
|
@@ -11,5 +11,7 @@
|
|
|
11
11
|
- lingzhu_safety_rule: request only actions that are clearly justified by the current quest and understandable to the human user
|
|
12
12
|
- lingzhu_text_rule: even when requesting `surface_actions`, always include a clear text explanation of what is happening and why
|
|
13
13
|
- lingzhu_reply_style_rule: for Lingzhu-facing user-visible text sent through `artifact.interact(...)`, keep the message clear, concise, respectful, and high-information-density
|
|
14
|
-
- lingzhu_reply_length_rule: for each Lingzhu-facing `artifact.interact(...)` message, normally
|
|
14
|
+
- lingzhu_reply_length_rule: for each Lingzhu-facing `artifact.interact(...)` message, normally keep the text within about 20 Chinese characters or one very short sentence unless the user explicitly asks for more detail
|
|
15
15
|
- lingzhu_summary_first_rule: in Lingzhu-facing `artifact.interact(...)` messages, usually give only the synopsis and key facts needed for the user's next decision or understanding; avoid long preambles, repetition, and low-signal detail
|
|
16
|
+
- lingzhu_task_gate_rule: only treat a Lingzhu user utterance as a new quest instruction when the text explicitly starts with `我现在的任务是`; otherwise assume the device is polling for queued progress or buffered replies
|
|
17
|
+
- lingzhu_poll_rule: when Lingzhu is polling rather than giving a new task, return only the buffered progress checkpoints or the latest short status; do not reinterpret the poll text as a fresh instruction
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
# Weixin Connector Contract
|
|
2
|
+
|
|
3
|
+
- connector_contract_id: weixin
|
|
4
|
+
- connector_contract_scope: loaded only when Weixin is the active or bound external connector for this quest
|
|
5
|
+
- connector_contract_goal: use `artifact.interact(...)` as the main durable user-visible thread while respecting the Weixin iLink `context_token` reply model
|
|
6
|
+
- weixin_runtime_ack_rule: the Weixin bridge itself emits the immediate transport-level receipt acknowledgement before the model turn starts
|
|
7
|
+
- weixin_no_duplicate_ack_rule: do not waste your first model response or first `artifact.interact(...)` call on a second bare acknowledgement such as "received", "已收到", or "processing" when the bridge already sent that
|
|
8
|
+
- weixin_reply_style_rule: keep Weixin replies concise, milestone-first, respectful, and easy to scan on a phone
|
|
9
|
+
- weixin_reply_length_rule: for ordinary Weixin progress replies, normally use only 2 to 4 short sentences, or 3 short bullets at most
|
|
10
|
+
- weixin_summary_first_rule: start with the user-facing conclusion, then what it means, then the next action
|
|
11
|
+
- weixin_progress_shape_rule: make the current task, the main difficulty or latest real progress, and the next concrete measure explicit whenever possible
|
|
12
|
+
- weixin_eta_rule: for important long-running phases such as baseline reproduction, main experiments, analysis, or paper packaging, include a rough ETA or next check-in window when you can
|
|
13
|
+
- weixin_tool_call_keepalive_rule: for ordinary active work, prefer one concise Weixin progress update after roughly 10 tool calls when there is already a human-meaningful delta, and do not let work drift beyond roughly 20 tool calls or about 15 minutes without a user-visible checkpoint
|
|
14
|
+
- weixin_internal_detail_rule: omit worker names, retry counters, pending/running/completed counts, low-level file listings, and monitor-window narration unless the user explicitly asked for them or they change the recommended action
|
|
15
|
+
- weixin_translation_rule: translate internal execution and file-management work into user value instead of narrating tool or filesystem churn
|
|
16
|
+
- weixin_preflight_rule: before sending a Weixin-facing progress update, rewrite it if it still reads like a monitor log, execution diary, or file inventory
|
|
17
|
+
- weixin_operator_surface_rule: treat Weixin as an operator surface for concise coordination and milestone delivery, not as a full artifact browser
|
|
18
|
+
- weixin_default_text_rule: plain text is the default and safest Weixin mode
|
|
19
|
+
- weixin_context_token_rule: ordinary downstream replies rely on the runtime-managed `context_token`; do not invent your own reply token fields
|
|
20
|
+
- weixin_media_rule: Weixin supports native image, video, and file delivery through structured attachments; request them through `artifact.interact(..., attachments=[...])` instead of inventing inline tag syntax
|
|
21
|
+
- weixin_media_path_rule: when sending native Weixin media, prefer absolute local paths; remote URLs are allowed only when the bridge can download them safely
|
|
22
|
+
- weixin_media_path_priority_rule: prefer quest-local files under `artifacts/`, `experiments/`, `paper/`, or `userfiles/` over arbitrary external URLs
|
|
23
|
+
- weixin_media_hint_rule: when you need native Weixin media typing, set `connector_delivery={'weixin': {'media_kind': ...}}` on the attachment instead of relying only on filename suffixes
|
|
24
|
+
- weixin_inbound_media_rule: inbound image, video, and file messages can now enter the quest as attachments, including media-only inbound turns
|
|
25
|
+
- weixin_inbound_materialization_rule: inbound media is copied into quest-local `userfiles/weixin/...`; if the user sent media, read those quest-local files before continuing
|
|
26
|
+
- weixin_audio_output_rule: there is no native Weixin voice-message output branch; audio files fall back to ordinary file delivery, not Weixin voice messages
|
|
27
|
+
- weixin_partial_delivery_rule: the runtime now preflights native attachments before send and prefers a single combined Weixin message for text plus media, so do not assume text was already delivered if attachment preparation failed
|
|
28
|
+
- weixin_failure_rule: if `artifact.interact(...)` returns `attachment_issues` or `delivery_results` errors, treat that as a real delivery failure and adapt before assuming the user received the media
|
|
29
|
+
- weixin_first_followup_rule: after a new inbound Weixin message, your first substantive follow-up should either answer directly or give the first meaningful checkpoint and next action, not a second bare acknowledgement
|
|
30
|
+
|
|
31
|
+
## Weixin Runtime Capabilities
|
|
32
|
+
|
|
33
|
+
- always supported:
|
|
34
|
+
- concise plain-text Weixin replies through `artifact.interact(...)`
|
|
35
|
+
- ordinary threaded continuity through runtime-managed `context_token`
|
|
36
|
+
- automatic downstream reply-to-user behavior when a valid `context_token` has been seen for that user
|
|
37
|
+
- inbound text messages entering the quest as user turns
|
|
38
|
+
- inbound image, video, and file attachments being materialized into quest-local `userfiles/weixin/...`
|
|
39
|
+
- supported when you attach one structured attachment with explicit delivery hints:
|
|
40
|
+
- native Weixin image delivery
|
|
41
|
+
- native Weixin video delivery
|
|
42
|
+
- native Weixin file delivery
|
|
43
|
+
- do not assume:
|
|
44
|
+
- inline connector-specific tags in the message body
|
|
45
|
+
- arbitrary historical quote reconstruction beyond the active `context_token`
|
|
46
|
+
- device-side `surface_actions`
|
|
47
|
+
- native Weixin voice-message output
|
|
48
|
+
|
|
49
|
+
## Structured Usage Rules
|
|
50
|
+
|
|
51
|
+
- request native Weixin image delivery by attaching one structured attachment with:
|
|
52
|
+
- `connector_delivery={'weixin': {'media_kind': 'image'}}`
|
|
53
|
+
- request native Weixin video delivery by attaching one structured attachment with:
|
|
54
|
+
- `connector_delivery={'weixin': {'media_kind': 'video'}}`
|
|
55
|
+
- request native Weixin file delivery by attaching one structured attachment with:
|
|
56
|
+
- `connector_delivery={'weixin': {'media_kind': 'file'}}`
|
|
57
|
+
- when you want native Weixin media delivery, make sure the attachment exposes at least one usable file reference such as:
|
|
58
|
+
- `path`
|
|
59
|
+
- `source_path`
|
|
60
|
+
- `output_path`
|
|
61
|
+
- `artifact_path`
|
|
62
|
+
- `url`
|
|
63
|
+
- if no native media delivery is needed, omit `connector_delivery`
|
|
64
|
+
- do not attach many files to Weixin by default; choose only the one highest-value image, video, or file for that milestone
|
|
65
|
+
- if native delivery fails, fall back to a concise text update unless the missing media is essential
|
|
66
|
+
- if the user sent media into Weixin, prefer the quest-local copied attachment path over connector cache or remote URL
|
|
67
|
+
|
|
68
|
+
## Examples
|
|
69
|
+
|
|
70
|
+
### 0. Bad vs good Weixin progress update
|
|
71
|
+
|
|
72
|
+
Bad:
|
|
73
|
+
|
|
74
|
+
```text
|
|
75
|
+
我刚看完新的一轮监控窗,现在还是 12 pending / 3 running / 1 completed。retry 计数已经到第 4 次,workspace 里又多了几个 png 和 json。我接下来继续盯日志和文件变动,之后再看看是不是还要再补一轮。
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Why bad:
|
|
79
|
+
|
|
80
|
+
- it forces the user to infer the real conclusion from internal telemetry
|
|
81
|
+
- it exposes retry counters, queue numbers, and file churn that usually do not help a phone-side operator
|
|
82
|
+
- it reads like a monitor log, not a concise collaborator update
|
|
83
|
+
|
|
84
|
+
Good:
|
|
85
|
+
|
|
86
|
+
```text
|
|
87
|
+
主实验还在继续推进,当前不需要您额外处理。最新进展是核心结果已经基本稳定,但还有一条对照线比较慢。接下来我会补完这条对照,预计 20 分钟左右给您下一次关键更新。
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Why good:
|
|
91
|
+
|
|
92
|
+
- it starts with the conclusion the user actually needs
|
|
93
|
+
- it keeps the meaningful risk but removes low-level runtime chatter
|
|
94
|
+
- it tells the user what happens next and when to expect the next checkpoint
|
|
95
|
+
|
|
96
|
+
### 1. Plain-text Weixin progress update
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
artifact.interact(
|
|
100
|
+
kind="progress",
|
|
101
|
+
message="主实验第一轮已经跑完,当前结果基本稳定。接下来我会继续补关键对照,确认这个提升是不是稳得住。预计下一次关键更新在 20 分钟左右。",
|
|
102
|
+
reply_mode="threaded",
|
|
103
|
+
)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### 2. Continue the current Weixin thread normally
|
|
107
|
+
|
|
108
|
+
Use the normal `artifact.interact(...)` call. The runtime keeps continuity through the latest `context_token` for that Weixin user.
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
artifact.interact(
|
|
112
|
+
kind="progress",
|
|
113
|
+
message="我已经看完您刚才发来的材料,也确认了它和当前 baseline 的关键差异。接下来我会把真正影响路线判断的部分整理出来,再给您一个更完整的结论。",
|
|
114
|
+
reply_mode="threaded",
|
|
115
|
+
)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### 3. Send one native Weixin image
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
artifact.interact(
|
|
122
|
+
kind="milestone",
|
|
123
|
+
message="主实验已经完成。我发一张汇总图给您,方便直接在手机上看。",
|
|
124
|
+
reply_mode="threaded",
|
|
125
|
+
attachments=[
|
|
126
|
+
{
|
|
127
|
+
"kind": "path",
|
|
128
|
+
"path": "/absolute/path/to/main_summary.png",
|
|
129
|
+
"label": "main-summary",
|
|
130
|
+
"content_type": "image/png",
|
|
131
|
+
"connector_delivery": {"weixin": {"media_kind": "image"}},
|
|
132
|
+
}
|
|
133
|
+
],
|
|
134
|
+
)
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### 4. Send one native Weixin video
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
artifact.interact(
|
|
141
|
+
kind="milestone",
|
|
142
|
+
message="我把这段关键演示视频一起发给您。",
|
|
143
|
+
reply_mode="threaded",
|
|
144
|
+
attachments=[
|
|
145
|
+
{
|
|
146
|
+
"kind": "path",
|
|
147
|
+
"path": "/absolute/path/to/demo.mp4",
|
|
148
|
+
"label": "demo-video",
|
|
149
|
+
"content_type": "video/mp4",
|
|
150
|
+
"connector_delivery": {"weixin": {"media_kind": "video"}},
|
|
151
|
+
}
|
|
152
|
+
],
|
|
153
|
+
)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### 5. Send one native Weixin file
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
artifact.interact(
|
|
160
|
+
kind="milestone",
|
|
161
|
+
message="论文初稿已经整理完成,我把 PDF 一并发给您。",
|
|
162
|
+
reply_mode="threaded",
|
|
163
|
+
attachments=[
|
|
164
|
+
{
|
|
165
|
+
"kind": "path",
|
|
166
|
+
"path": "/absolute/path/to/paper_draft.pdf",
|
|
167
|
+
"label": "paper-draft",
|
|
168
|
+
"content_type": "application/pdf",
|
|
169
|
+
"connector_delivery": {"weixin": {"media_kind": "file"}},
|
|
170
|
+
}
|
|
171
|
+
],
|
|
172
|
+
)
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### 6. Send a native Weixin image from an artifact-style path field
|
|
176
|
+
|
|
177
|
+
If the attachment is not using `path` but does expose a real quest-local file through `source_path`, `output_path`, or `artifact_path`, the runtime can still use it for native Weixin media delivery.
|
|
178
|
+
|
|
179
|
+
```python
|
|
180
|
+
artifact.interact(
|
|
181
|
+
kind="milestone",
|
|
182
|
+
message="我把这张结果图直接发给您。",
|
|
183
|
+
reply_mode="threaded",
|
|
184
|
+
attachments=[
|
|
185
|
+
{
|
|
186
|
+
"kind": "runner_result",
|
|
187
|
+
"source_path": "/absolute/path/to/result.png",
|
|
188
|
+
"content_type": "image/png",
|
|
189
|
+
"connector_delivery": {"weixin": {"media_kind": "image"}},
|
|
190
|
+
}
|
|
191
|
+
],
|
|
192
|
+
)
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### 7. If the user sent Weixin media into the quest
|
|
196
|
+
|
|
197
|
+
- inspect the current turn attachments
|
|
198
|
+
- prefer the copied quest-local file under `userfiles/weixin/...`
|
|
199
|
+
- reason over that local file instead of asking the user to resend unless the attachment is broken
|
|
200
|
+
|
|
201
|
+
### 8. If delivery fails
|
|
202
|
+
|
|
203
|
+
- inspect `attachment_issues`
|
|
204
|
+
- inspect `delivery_results`
|
|
205
|
+
- if native media failed, send a concise text-only fallback unless the missing media is essential
|
|
206
|
+
|
|
207
|
+
Example fallback shape:
|
|
208
|
+
|
|
209
|
+
```python
|
|
210
|
+
result = artifact.interact(
|
|
211
|
+
kind="milestone",
|
|
212
|
+
message="我把汇总图发给您。",
|
|
213
|
+
reply_mode="threaded",
|
|
214
|
+
attachments=[
|
|
215
|
+
{
|
|
216
|
+
"kind": "path",
|
|
217
|
+
"path": "/absolute/path/to/main_summary.png",
|
|
218
|
+
"content_type": "image/png",
|
|
219
|
+
"connector_delivery": {"weixin": {"media_kind": "image"}},
|
|
220
|
+
}
|
|
221
|
+
],
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
if result.get("attachment_issues") or any(not item.get("ok") for item in (result.get("delivery_results") or [])):
|
|
225
|
+
artifact.interact(
|
|
226
|
+
kind="progress",
|
|
227
|
+
message="图片这次没有成功送达。我先继续用文字给您同步结论,稍后再补发可用版本。",
|
|
228
|
+
reply_mode="threaded",
|
|
229
|
+
)
|
|
230
|
+
```
|
package/src/prompts/system.md
CHANGED
|
@@ -978,12 +978,15 @@ Prefer these patterns:
|
|
|
978
978
|
- treat the resulting branch as one durable research round or route, not merely a temporary Git container
|
|
979
979
|
- every accepted durable idea submission should normally create a new user-visible canvas node
|
|
980
980
|
- before accepting an idea, unless strong durable evidence already narrows the route to one obvious serious option, run one bounded divergent -> convergent ideation pass instead of collapsing onto the first plausible route
|
|
981
|
+
- before writing or submitting the final selected idea, durably map at least 5 and usually 5 to 10 related and usable papers; prioritize direct task-modeling or mechanism-neighbor papers and only backfill with the closest adjacent translatable work when the direct pool is truly smaller
|
|
981
982
|
- classify the current framing as `problem-first` or `solution-first`
|
|
982
983
|
- generate a small but genuinely diverse candidate slate before ranking, then shrink it back to a serious frontier that is usually 2 to 3 alternatives and at most 5
|
|
983
984
|
- if the candidates are all from the same mechanism family, widen once with distinct lenses such as abstraction ladder, tension hunting, analogy transfer, inversion, or adjacent-possible reasoning
|
|
984
985
|
- require each serious candidate to answer `why now` / `what changed`
|
|
985
986
|
- before `artifact.submit_idea(...)`, make the winner pass a two-sentence pitch and strongest-objection check
|
|
986
987
|
- before calling it, first finish a concise but durable idea draft in Markdown that explains the route clearly enough for later implementation and review
|
|
988
|
+
- do not treat the literature floor as optional; if fewer than 5 usable papers are durably mapped, go back to search or record a blocked state instead of forcing the idea through
|
|
989
|
+
- that final idea draft must use one consistent standard citation format and include a `References` or `Bibliography` section for the survey-stage papers that actually shaped the idea
|
|
987
990
|
- when available, pass that draft through `draft_markdown` so the branch keeps both a compact `idea.md` contract and a richer `draft.md`
|
|
988
991
|
- `continue_line` means the new idea is a child of the current active branch
|
|
989
992
|
- `branch_alternative` means the new idea is a sibling-like branch that starts from the current branch's parent foundation
|
|
@@ -1042,6 +1045,8 @@ Prefer these patterns:
|
|
|
1042
1045
|
- use `artifact.checkpoint(...)` for meaningful code-state milestones
|
|
1043
1046
|
- use `artifact.render_git_graph(...)` when the quest needs a refreshed Git history view
|
|
1044
1047
|
- use `artifact.arxiv(paper_id=..., full_text=False)` to read an already identified arXiv paper
|
|
1048
|
+
- `artifact.arxiv(mode='read', paper_id=..., full_text=False)` is the preferred explicit form; it is local-first and will auto-persist the paper into the quest arXiv library when missing
|
|
1049
|
+
- use `artifact.arxiv(mode='list')` when you need to inspect the arXiv papers already saved for the current quest
|
|
1045
1050
|
- keep paper discovery in web search; switch to `artifact.arxiv(..., full_text=True)` only when the full paper body is actually needed
|
|
1046
1051
|
- use stage-significant artifact writes for progress, milestone, report, run, and decision updates
|
|
1047
1052
|
- if the runtime exposes `artifact.interact(...)`, use it for structured progress updates, decision requests, and approval responses
|
|
@@ -1626,6 +1631,9 @@ If you choose a non-default foundation, record why.
|
|
|
1626
1631
|
At the start of `idea`, if related-work coverage or novelty judgment is not already durable and explicit, also open `scout/SKILL.md` as a companion skill before final selection.
|
|
1627
1632
|
At the start of a fresh or resumed `idea` pass, search quest/global memory first.
|
|
1628
1633
|
If coverage is still incomplete or stale, actively use the runner's web/search tool for discovery and `artifact.arxiv(...)` for reading shortlisted arXiv papers before selecting a direction.
|
|
1634
|
+
Treat literature grounding as a hard gate: do not write or submit a final selected idea until the durable survey covers at least 5 and usually 5 to 10 related and usable papers.
|
|
1635
|
+
Those papers should be close enough to the task-modeling problem, failure mode, mechanism, or codebase translation question to justify the selected route with real evidence rather than intuition alone.
|
|
1636
|
+
If the direct neighborhood is genuinely smaller, document that shortage explicitly and use the closest adjacent translatable papers to finish the grounding.
|
|
1629
1637
|
|
|
1630
1638
|
Expected outcomes:
|
|
1631
1639
|
|
|
@@ -1640,6 +1648,7 @@ Expected outcomes:
|
|
|
1640
1648
|
- explicit mechanism and risk
|
|
1641
1649
|
- cheapest falsification path
|
|
1642
1650
|
- selected direction or rejection decision
|
|
1651
|
+
- a final idea draft that uses standard-format citations and a `References` or `Bibliography` section for the papers actually used
|
|
1643
1652
|
- when the pass is substantial, a research-outline style note can be preferable to loose ideation prose; that note should usually cover:
|
|
1644
1653
|
- executive summary
|
|
1645
1654
|
- codebase analysis
|
package/src/skills/idea/SKILL.md
CHANGED
|
@@ -103,6 +103,9 @@ Break ties primarily through careful reasoning over:
|
|
|
103
103
|
- Do not select an idea before checking whether close prior work already did it.
|
|
104
104
|
- Do not confuse "I can implement this" with "this is a publishable or useful research direction".
|
|
105
105
|
- Do not treat a weak literature search as sufficient because the idea sounds elegant.
|
|
106
|
+
- Do not write, promote, or submit a final idea until the durable survey covers at least `5` and usually `5-10` task-modeling-related, mechanism-relevant, or otherwise directly usable papers.
|
|
107
|
+
- Treat that literature floor as a hard gate, not a suggestion.
|
|
108
|
+
If the direct task-modeling neighborhood truly contains fewer than `5` usable papers, record that evidence explicitly and fill the remaining slots with the closest adjacent papers whose mechanism can be translated into the current task and codebase.
|
|
106
109
|
- Every fresh idea build or idea-refinement pass must begin with:
|
|
107
110
|
- a memory sweep, and
|
|
108
111
|
- an external literature sweep.
|
|
@@ -206,6 +209,8 @@ Before you choose a direction, perform a broad but bounded literature sweep.
|
|
|
206
209
|
|
|
207
210
|
The sweep must be grounded in actual retrieval, not recall alone.
|
|
208
211
|
If durable quest memory already contains a recent and explicit survey, reuse it first and search externally only for the missing buckets, newer papers, or unresolved overlaps.
|
|
212
|
+
For a normal selected-idea decision, the durable sweep must end with at least `5` and usually `5-10` papers that are close enough to the task-modeling problem, failure mode, mechanism, or codebase translation question to inform the actual design.
|
|
213
|
+
This floor exists to prevent thin novelty claims and under-motivated ideas, not to reward quota chasing.
|
|
209
214
|
|
|
210
215
|
When tools allow it, combine:
|
|
211
216
|
|
|
@@ -240,6 +245,8 @@ For each promising idea, you must be able to answer:
|
|
|
240
245
|
|
|
241
246
|
The goal is not to cite everything on Earth.
|
|
242
247
|
The goal is to avoid fake novelty and to identify a direction that has credible research value.
|
|
248
|
+
However, do not stop the sweep early once the first plausible argument appears.
|
|
249
|
+
Keep going until the strongest obvious overlaps are mapped and the `5-10` usable-paper floor is durably satisfied.
|
|
243
250
|
|
|
244
251
|
Recommended search outputs:
|
|
245
252
|
|
|
@@ -962,9 +969,15 @@ At minimum, preserve:
|
|
|
962
969
|
- a `why now` statement
|
|
963
970
|
- the code-level plan and minimal experiment
|
|
964
971
|
- the literature relation and evidence pointers
|
|
972
|
+
- inline citations or citation markers tied to the papers actually used in the idea rationale
|
|
973
|
+
- a `References` or `Bibliography` section in a standard citation format
|
|
965
974
|
- the strongest alternative hypothesis
|
|
966
975
|
- the strongest likely objection
|
|
967
976
|
|
|
977
|
+
The selected idea draft must cite the survey papers that actually shaped the mechanism, motivation, novelty check, or claim boundary.
|
|
978
|
+
Use one consistent standard citation format throughout the draft, such as numbered references or author-year style.
|
|
979
|
+
Do not mention paper titles casually in prose without giving them a proper citation entry.
|
|
980
|
+
|
|
968
981
|
## Idea quality rules
|
|
969
982
|
|
|
970
983
|
Good ideas should be:
|
|
@@ -1135,6 +1148,7 @@ Preferred artifact choices:
|
|
|
1135
1148
|
|
|
1136
1149
|
If the idea is selected and becomes the active route, immediately call `artifact.submit_idea(mode='create', lineage_intent='continue_line'|'branch_alternative', ...)`.
|
|
1137
1150
|
Before that call, first finalize a concise but durable Markdown draft for the chosen route.
|
|
1151
|
+
Do not start writing that final draft until the literature survey has already met the hard minimum of at least `5` and usually `5-10` usable papers.
|
|
1138
1152
|
That draft should usually cover:
|
|
1139
1153
|
|
|
1140
1154
|
- executive summary
|
|
@@ -1148,9 +1162,11 @@ That draft should usually cover:
|
|
|
1148
1162
|
- code-level change plan
|
|
1149
1163
|
- evaluation or falsification plan
|
|
1150
1164
|
- risks, caveats, and implementation notes
|
|
1165
|
+
- a citation-ready `References` or `Bibliography` section that lists the survey-stage papers actually used by the idea in a standard citation format
|
|
1151
1166
|
|
|
1152
1167
|
Use the draft to think clearly first, then compress the accepted contract into the structured `artifact.submit_idea(...)` fields.
|
|
1153
1168
|
When the MCP surface supports it, pass the final Markdown draft through `draft_markdown` so the branch records both `idea.md` and `draft.md`.
|
|
1169
|
+
Ensure the final draft carries appropriate citations for the closest prior work, direct inspirations, and any cross-domain papers that materially shaped the selected idea.
|
|
1154
1170
|
Normal durable idea flow should create a new branch and a new canvas node every time an accepted idea package changes meaningfully, including documentation-only idea-package changes.
|
|
1155
1171
|
Use `lineage_intent='continue_line'` when the new idea is a child of the current active branch.
|
|
1156
1172
|
Use `lineage_intent='branch_alternative'` when the new idea should branch from the current branch's parent foundation as a sibling-like alternative.
|
|
@@ -11,6 +11,11 @@ The purpose is to make related-work coverage durable, searchable, and reusable s
|
|
|
11
11
|
- baseline id or method name
|
|
12
12
|
- task / dataset / metric contract
|
|
13
13
|
- current investigation target
|
|
14
|
+
- survey minimum gate status
|
|
15
|
+
- related and usable papers found so far
|
|
16
|
+
- how many are direct task-modeling papers
|
|
17
|
+
- how many are adjacent but translatable papers
|
|
18
|
+
- whether the hard floor of at least `5` and usually `5-10` usable papers has been satisfied
|
|
14
19
|
- why the survey is being run now
|
|
15
20
|
- first idea build
|
|
16
21
|
- idea refinement
|
|
@@ -66,9 +71,11 @@ For each paper, include:
|
|
|
66
71
|
- year
|
|
67
72
|
- identifier or arXiv id
|
|
68
73
|
- URL
|
|
74
|
+
- standard citation string or citation key
|
|
69
75
|
- short mechanism summary
|
|
70
76
|
- task / dataset / metric overlap
|
|
71
77
|
- what it means for the current idea
|
|
78
|
+
- whether it is directly usable for the current idea, only a novelty check, or only an adjacent inspiration
|
|
72
79
|
- status:
|
|
73
80
|
- `new_this_pass`
|
|
74
81
|
- `known_before`
|
|
@@ -80,6 +87,7 @@ Recommended columns:
|
|
|
80
87
|
|
|
81
88
|
- identifier
|
|
82
89
|
- year
|
|
90
|
+
- standard citation key
|
|
83
91
|
- mechanism overlap
|
|
84
92
|
- task overlap
|
|
85
93
|
- dataset overlap
|
|
@@ -129,3 +137,19 @@ Close with:
|
|
|
129
137
|
- the rejected ideas and why
|
|
130
138
|
- what still needs more search before selection
|
|
131
139
|
- whether the stage is ready for `idea` selection, more `scout`, or a user decision
|
|
140
|
+
|
|
141
|
+
## 10. Citation-ready shortlist for the selected idea
|
|
142
|
+
|
|
143
|
+
Before the final idea draft is written, extract the papers that materially support the winning idea.
|
|
144
|
+
|
|
145
|
+
For each such paper, include:
|
|
146
|
+
|
|
147
|
+
- standard citation entry in the format you plan to use later
|
|
148
|
+
- what part of the idea it supports:
|
|
149
|
+
- problem motivation
|
|
150
|
+
- closest prior work
|
|
151
|
+
- mechanism inspiration
|
|
152
|
+
- claim boundary
|
|
153
|
+
- whether it must appear inline in the idea draft or only in the references section
|
|
154
|
+
|
|
155
|
+
The final selected idea should not be written or submitted until this shortlist is ready.
|
|
@@ -52,6 +52,9 @@ Try to cover these buckets before final selection:
|
|
|
52
52
|
- papers focused on the same failure mode
|
|
53
53
|
- papers with the same task but different mechanism families
|
|
54
54
|
|
|
55
|
+
For a normal selected-idea decision, the survey should durably cover at least `5` and usually `5-10` related and usable papers.
|
|
56
|
+
Prefer direct task-modeling papers first; if that pool is truly small, fill the rest with the closest adjacent and translatable work instead of pretending the literature is empty.
|
|
57
|
+
|
|
55
58
|
If the area is active, recent work matters a lot.
|
|
56
59
|
If the area is stable, seminal work may matter more than recency.
|
|
57
60
|
|
|
@@ -132,4 +135,5 @@ The related-work search is good enough to stop when:
|
|
|
132
135
|
- the strongest obvious nearby papers are mapped
|
|
133
136
|
- the closest-prior-work table is complete enough to compare seriously
|
|
134
137
|
- each top candidate has an explicit novelty or value verdict
|
|
138
|
+
- the usable-paper floor for the selected idea has been satisfied or the shortage is explicitly documented
|
|
135
139
|
- the remaining uncertainty is recorded rather than hidden
|