Compare commits

...

2 Commits

5 changed files with 143 additions and 0 deletions

View File

@ -6,3 +6,28 @@ GroundRecall is a human-reviewable/AI usable knowledge layer with capabilities t
source material began as legacy office documents and you want a provenance-aware source material began as legacy office documents and you want a provenance-aware
knowledge import without going through a learner pack first. See knowledge import without going through a learner pack first. See
`docs/quickstart.md` for the minimal `doclift -> GroundRecall` flow. `docs/quickstart.md` for the minimal `doclift -> GroundRecall` flow.
`GroundRecall` can now also export a pack-ready
`groundrecall_query_bundle.json` for a reviewed concept so `Didactopus` can
carry that concept context into a learner-facing pack:
```bash
python -m groundrecall.export /path/to/groundrecall-store /tmp/groundrecall-export \
--pack-ready-concept channel-capacity
```
The matching `Didactopus` bridge flow is:
```bash
didactopus doclift-bundle-groundrecall \
/path/to/groundrecall-store \
channel-capacity \
/tmp/doclift-bundle \
/tmp/didactopus-pack \
--course-title "Example Course"
```
See:
- `docs/quickstart.md`
- `docs/didactopus-bridge.md`

84
docs/didactopus-bridge.md Normal file
View File

@ -0,0 +1,84 @@
# Didactopus Bridge
This documents the `GroundRecall` side of the bridge into a learner-facing
`Didactopus` pack.
## Purpose
Use this when:
- you already have a reviewed concept in a canonical `GroundRecall` store
- your source material also exists as a normalized `doclift` bundle
- you want `Didactopus` to generate a learner-facing pack that carries the
reviewed concept context along with the ordinary pack artifacts
`GroundRecall` remains the canonical reviewed knowledge layer.
`Didactopus` remains the learner-facing pack and workbench layer.
## Minimal Export
Export a pack-ready query bundle directly from the `GroundRecall` store:
```bash
groundrecall export /path/to/groundrecall-store /tmp/groundrecall-export \
--pack-ready-concept channel-capacity
```
That writes:
- `/tmp/groundrecall-export/groundrecall_query_bundle.json`
It also records the path in `export_manifest.json`.
## End-To-End Bridge
The shortest full bridge path is:
```bash
doclift convert-dir /path/to/legacy-course /tmp/doclift-bundle --asset-root /path/to/legacy-course
didactopus doclift-bundle-groundrecall \
/path/to/groundrecall-store \
channel-capacity \
/tmp/doclift-bundle \
/tmp/didactopus-pack \
--course-title "Example Course"
```
That command:
1. exports `groundrecall_query_bundle.json` for the selected concept
2. passes that file into the `Didactopus` `doclift` bundle demo workflow
3. writes a generated pack that includes the GroundRecall bundle as a declared
supporting artifact
## Outputs
On the `GroundRecall` side:
- canonical store remains unchanged
- export directory contains `groundrecall_query_bundle.json`
On the `Didactopus` side:
- generated pack contains `groundrecall_query_bundle.json`
- the pack summary records that the GroundRecall bundle was included
- learner-workbench flows can consume the review and graph context from that
bundle
## Why This Boundary Matters
This keeps responsibilities clean:
- `doclift` normalizes document corpora
- `GroundRecall` owns canonical reviewed concept/query context
- `Didactopus` owns learner-facing packs, workbenches, and pedagogy workflows
The bridge exists so those systems can cooperate without collapsing into one
repository boundary or one data model.
## Related Documentation
- [quickstart.md](quickstart.md)
- [architecture.md](architecture.md)
- `Didactopus`: `docs/groundrecall-bridge.md`

View File

@ -84,6 +84,12 @@ Export assistant-neutral artifacts:
groundrecall export store/ exports/groundrecall --concept channel-capacity groundrecall export store/ exports/groundrecall --concept channel-capacity
``` ```
Export a pack-ready `groundrecall_query_bundle.json` for `Didactopus`:
```bash
groundrecall export store/ exports/groundrecall --pack-ready-concept channel-capacity
```
Export assistant-targeted bundles: Export assistant-targeted bundles:
```bash ```bash
@ -91,6 +97,28 @@ groundrecall assistant-export store/ codex exports/codex --concept channel-capac
groundrecall assistant-export store/ claude_code exports/claude --concept channel-capacity groundrecall assistant-export store/ claude_code exports/claude --concept channel-capacity
``` ```
## Bridge To Didactopus
If you want a `Didactopus` learner pack that carries reviewed GroundRecall
concept context, the shortest bridge flow is:
```bash
doclift convert-dir /path/to/legacy-course /tmp/doclift-bundle --asset-root /path/to/legacy-course
didactopus doclift-bundle-groundrecall \
store/ \
channel-capacity \
/tmp/doclift-bundle \
/tmp/didactopus-pack \
--course-title "Example Course"
```
That command:
- exports a pack-ready `groundrecall_query_bundle.json` from `GroundRecall`
- feeds it into the `Didactopus` `doclift` bundle flow
- writes a pack with the GroundRecall query bundle included as a declared
supporting artifact
## Default Working Layout ## Default Working Layout
A simple local layout is: A simple local layout is:
@ -108,5 +136,6 @@ The current alpha does not require this exact layout, but it is a sensible start
## Next Reading ## Next Reading
- [architecture.md](architecture.md) - [architecture.md](architecture.md)
- [didactopus-bridge.md](didactopus-bridge.md)
- [llmwiki-import.md](llmwiki-import.md) - [llmwiki-import.md](llmwiki-import.md)
- [sync-roadmap.md](sync-roadmap.md) - [sync-roadmap.md](sync-roadmap.md)

View File

@ -155,6 +155,7 @@ def build_query_bundle_for_concept(store_dir: str | Path, concept_ref: str) -> d
if payload is None: if payload is None:
return None return None
claims = payload["claims"] claims = payload["claims"]
relations = payload["relations"]
contradictions = [item for item in claims if item.get("contradicts_claim_ids")] contradictions = [item for item in claims if item.get("contradicts_claim_ids")]
supersessions = [item for item in claims if item.get("supersedes_claim_ids")] supersessions = [item for item in claims if item.get("supersedes_claim_ids")]
return { return {
@ -162,7 +163,9 @@ def build_query_bundle_for_concept(store_dir: str | Path, concept_ref: str) -> d
"query_type": "concept", "query_type": "concept",
"concept": payload["concept"], "concept": payload["concept"],
"relevant_claims": claims, "relevant_claims": claims,
"relations": relations,
"supporting_observations": payload["supporting_observations"], "supporting_observations": payload["supporting_observations"],
"source_artifacts": payload["source_artifacts"],
"related_concepts": payload["related_concepts"], "related_concepts": payload["related_concepts"],
"review_candidates": payload["review_candidates"], "review_candidates": payload["review_candidates"],
"contradictions": contradictions, "contradictions": contradictions,

View File

@ -171,6 +171,8 @@ def test_build_query_bundle_for_concept_is_assistant_neutral(tmp_path: Path) ->
assert payload is not None assert payload is not None
assert payload["bundle_kind"] == "groundrecall_query_bundle" assert payload["bundle_kind"] == "groundrecall_query_bundle"
assert payload["concept"]["concept_id"] == "concept::channel-capacity" assert payload["concept"]["concept_id"] == "concept::channel-capacity"
assert len(payload["relations"]) == 1
assert payload["source_artifacts"][0]["artifact_id"] == "ia_001"
assert len(payload["review_candidates"]) == 2 assert len(payload["review_candidates"]) == 2
assert isinstance(payload["suggested_next_actions"], list) assert isinstance(payload["suggested_next_actions"], list)
forbidden = {"assistant", "codex", "claude", "prompt_text"} forbidden = {"assistant", "codex", "claude", "prompt_text"}