Skip to content

Commit 68b712f

Browse files
authored
Merge pull request #3453 from now-ing/feat/deepresearch-command
feat(deepresearch): add /loopx-deepresearch bounded research loop
2 parents 4ce4786 + 534b2e1 commit 68b712f

12 files changed

Lines changed: 2509 additions & 0 deletions

File tree

‎loopx/capabilities/catalog.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from .value_connectors.catalog_entry import VALUE_CONNECTORS_CATALOG_ENTRY
2525
from .explore.catalog_entry import EXPLORE_CATALOG_ENTRY
2626
from .auto_research.catalog_entry import AUTO_RESEARCH_CATALOG_ENTRY
27+
from .deep_research.catalog_entry import DEEP_RESEARCH_CATALOG_ENTRY
2728
from .public_safe_outbound.catalog_entry import PUBLIC_SAFE_OUTBOUND_CATALOG_ENTRY
2829
from .connector_registry.catalog_entry import CONNECTOR_REGISTRY_CATALOG_ENTRY
2930
from .registry import CapabilityRegistry
@@ -50,6 +51,7 @@
5051
VALUE_CONNECTORS_CATALOG_ENTRY,
5152
EXPLORE_CATALOG_ENTRY,
5253
AUTO_RESEARCH_CATALOG_ENTRY,
54+
DEEP_RESEARCH_CATALOG_ENTRY,
5355
PUBLIC_SAFE_OUTBOUND_CATALOG_ENTRY,
5456
CONNECTOR_REGISTRY_CATALOG_ENTRY,
5557
)
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Deep research (evidence-ledger research loop)
2+
3+
`/loopx-deepresearch` turns one user question into a bounded, auditable research
4+
session: question, source, claim, and contradiction ledgers live in
5+
`.loopx/deepresearch/research.json`, the packet (`loopx deepresearch status`)
6+
owns what to research next and when to stop, and the final report keeps every
7+
citation resolvable to a recorded source.
8+
9+
## Boundary with auto-research
10+
11+
The built-in `auto-research` capability and this capability both do "bounded
12+
research" but own different truths and must not be merged casually:
13+
14+
| | auto-research | deep-research (this) |
15+
| --- | --- | --- |
16+
| Unit of work | a LoopX **goal** with role-scoped workers | one **session ledger** in a project |
17+
| State authority | goal todos, hypotheses, rollout events | `.loopx/deepresearch/` ledger |
18+
| Progression | worker contract + terminal decision/review | packet expeditions + stop conditions |
19+
| Output | promoted/retired hypotheses in canonical evidence | citation-auditable markdown report |
20+
| Use when | open exploration inside the LoopX control plane | a single user question needing an auditable, source-cited answer |
21+
22+
Choose one per question; they do not share state and neither can close the
23+
other's work.
24+
25+
## Boundary with explore
26+
27+
The `explore` capability owns the goal-scoped, public-safe, cross-session
28+
knowledge topology (questions, findings, evidence relations). deep-research owns
29+
a private, session-scoped transactional ledger:
30+
31+
- deep-research keeps raw source locators (URLs or local paths that may not be
32+
safe to publish), claim lineage, precise contradiction pairs with sides-with
33+
adjudication, stop/close decisions, and the citation report. It works
34+
standalone — with no LoopX goal and no explore opt-in.
35+
- explore keeps the canonical, reusable projection. Any future bridge is a
36+
one-way, idempotent, public-safe derivation: explore receives sanitized,
37+
opaque evidence refs only; it never reads the raw deep-research ledger or
38+
report, never dual-writes research state, and a graph node resolving never
39+
closes (or reopens) a research run.
40+
41+
In short: deep-research is the only writer of `.loopx/deepresearch/`, and
42+
public surfaces only ever see derived, reconstructable projections.
43+
44+
One ledger invariant spans every transition that adjudicates a contradiction:
45+
no resolution — inside `resolve-question` or standalone
46+
`resolve-contradiction` — may overrule a claim that an already-answered
47+
question cites as evidence. The ledger never silently invalidates a recorded
48+
answer; late-arriving counterevidence that wins forces an explicit decision
49+
(side with the cited claim, or close the run and revisit the question in a new
50+
run) instead of leaving the report internally inconsistent.
51+
52+
## Lifecycle
53+
54+
`start` opens a run; `close` is the explicit terminal transition; the next
55+
`start` archives the closed run (state + report) under
56+
`.loopx/deepresearch/archive/<closed-at>/` and begins fresh. `start --new-run`
57+
auto-closes only a run whose stop conditions already fired; an active run
58+
always requires an explicit `close` first. State files are only ever rotated by
59+
these typed transitions — never edited by hand.
60+
61+
## Layout
62+
63+
- Domain state machine and report (capability owner):
64+
`loopx/capabilities/deep_research/runtime.py`
65+
- CLI adapter: `loopx/cli_commands/deepresearch.py` (`loopx deepresearch …`)
66+
- Host entry: the `/loopx-deepresearch` skill facade installed by
67+
`loopx slash-commands --install`
68+
69+
Recorded claims carry caller-declared provenance: `--tool` records the tool the
70+
caller says produced the evidence. The CLI records that provenance; it does not
71+
attest that the tool actually ran — execution receipts belong to a future
72+
host/harness bridge, not this ledger.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from __future__ import annotations
2+
3+
from .catalog_entry import DEEP_RESEARCH_CATALOG_ENTRY
4+
5+
__all__ = ["DEEP_RESEARCH_CATALOG_ENTRY"]
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
from __future__ import annotations
2+
3+
from typing import Any
4+
5+
6+
DEEP_RESEARCH_CATALOG_ENTRY: dict[str, Any] = {
7+
"id": "deep-research",
8+
"origin": "builtin",
9+
"visibility": "public",
10+
"provider_id": "loopx-core",
11+
"documentation": {
12+
"source_root": "loopx/capabilities/deep_research",
13+
"site_root": "capabilities/deep-research",
14+
"canonical": "README.md",
15+
},
16+
"title": "Evidence-ledger deep research loop",
17+
"status": "experimental",
18+
"real_world_anchor": (
19+
"one user question driven by packet-cut expeditions over question, source, "
20+
"claim, and contradiction ledgers, ending in a citation-auditable report"
21+
),
22+
"user_value": (
23+
"Run a bounded, auditable research session per project: claims must come from "
24+
"recorded sources, answers must cite recorded claims, and closeout is blocked "
25+
"while any contradiction stays unresolved."
26+
),
27+
"entry_command": "loopx deepresearch start --question <text>",
28+
"commands": [
29+
{
30+
"command": "loopx deepresearch start --question <text> [--max-sources N] [--new-run]",
31+
"purpose": "Open a research run; archives the previous closed/stopped run instead of editing state files by hand.",
32+
"write_boundary": ".loopx/deepresearch/ state and report files only",
33+
},
34+
{
35+
"command": "loopx deepresearch status",
36+
"purpose": "Emit the expedition packet: contract, ledgers, next expedition, stop conditions, evidence commands.",
37+
"write_boundary": "read-only projection over the research ledger",
38+
},
39+
{
40+
"command": "loopx deepresearch add-source --url-or-path <ref> --tool <tool> --claims-json <json>",
41+
"purpose": "Record one consulted source and the claims extracted from it.",
42+
"write_boundary": "one ledger transaction under the project research lock",
43+
},
44+
{
45+
"command": "loopx deepresearch add-subquestion --text <text> --from-claim <claim-id>",
46+
"purpose": "Open a subquestion that derives from a recorded claim.",
47+
"write_boundary": "one ledger transaction under the project research lock",
48+
},
49+
{
50+
"command": "loopx deepresearch resolve-question --question-id <id> --answer <text> --evidence-claims <ids>",
51+
"purpose": "Answer a recorded question citing recorded evidence claims; contradictions touching the evidence must be resolved in the same transition.",
52+
"write_boundary": "one ledger transaction under the project research lock",
53+
},
54+
{
55+
"command": "loopx deepresearch resolve-contradiction --contradiction-id <id> --sides-with <claim-id> --rationale <text>",
56+
"purpose": "Close one open contradiction standalone with an explicit sides-with rationale.",
57+
"write_boundary": "one ledger transaction under the project research lock",
58+
},
59+
{
60+
"command": "loopx deepresearch close [--note <text>]",
61+
"purpose": "Terminal transition marking this run closed and its ledger immutable; the next start archives it.",
62+
"write_boundary": "marks the run closed; the next start performs the archive rotation",
63+
},
64+
{
65+
"command": "loopx deepresearch report",
66+
"purpose": "Render the citation-auditable markdown report from the ledgers.",
67+
"write_boundary": "writes .loopx/deepresearch/report.md only",
68+
},
69+
],
70+
"implemented_protocols": [
71+
{
72+
"schema_version": "loopx_deepresearch_state_v0",
73+
"module": "loopx.capabilities.deep_research.runtime",
74+
"doc": "loopx/capabilities/deep_research/README.md",
75+
},
76+
{
77+
"schema_version": "loopx_deepresearch_packet_v0",
78+
"module": "loopx.capabilities.deep_research.runtime",
79+
"doc": "loopx/capabilities/deep_research/README.md",
80+
},
81+
],
82+
"smokes": [
83+
"python3 -m pytest tests/test_deepresearch_command.py -q",
84+
],
85+
"docs": [
86+
"loopx/capabilities/deep_research/README.md",
87+
],
88+
"boundaries": [
89+
(
90+
"Distinct from the auto-research capability: auto-research launches "
91+
"role-scoped workers inside a LoopX goal for open exploration; "
92+
"deep-research is a single-session, user-facing evidence ledger whose "
93+
"truth is the .loopx/deepresearch state, not goal todos."
94+
),
95+
(
96+
"Distinct from the explore capability: explore owns the goal-scoped, "
97+
"public-safe, cross-session question/finding topology; deep-research "
98+
"owns this private, session-scoped ledger — raw source locators, claim "
99+
"lineage, contradiction adjudication, stop/close/report. Any future "
100+
"bridge is a one-way, idempotent, public-safe projection: explore "
101+
"never reads the raw ledger, never dual-writes, and graph resolution "
102+
"never closes a research run."
103+
),
104+
(
105+
"The packet owns research progression and stop decisions; the model "
106+
"executes bounded expeditions and records typed ledger transitions only. "
107+
"No contradiction adjudication — in-call or standalone — may overrule "
108+
"a claim an already-answered question cites as evidence."
109+
),
110+
(
111+
"Claims carry caller-declared provenance: --tool records the tool the "
112+
"caller says produced the evidence, and the CLI records it without "
113+
"attesting execution; reports must keep every citation resolvable to a "
114+
"recorded source."
115+
),
116+
(
117+
"One active run per project; finished or closed runs are archived under "
118+
".loopx/deepresearch/archive/ by typed transitions, never by hand edits."
119+
),
120+
],
121+
"next_real_step": (
122+
"Keep the deep-research entrypoint as the single evidence-ledger authority and "
123+
"reuse LoopX goal/todo/quota projections rather than adding a second scheduler."
124+
),
125+
}

0 commit comments

Comments
 (0)