groundly 0.3.0__tar.gz
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.
- groundly-0.3.0/.claude/agents/adversarial-reviewer.md +53 -0
- groundly-0.3.0/.claude/agents/security-reviewer.md +34 -0
- groundly-0.3.0/.claude/agents/spec-guardian.md +33 -0
- groundly-0.3.0/.claude/rules/architecture.md +29 -0
- groundly-0.3.0/.claude/rules/conventions.md +25 -0
- groundly-0.3.0/.claude/rules/grounding-and-privacy.md +26 -0
- groundly-0.3.0/.claude/skills/decision/SKILL.md +22 -0
- groundly-0.3.0/.claude/skills/implement-uc/SKILL.md +22 -0
- groundly-0.3.0/.github/workflows/ci.yml +31 -0
- groundly-0.3.0/.github/workflows/publish.yml +39 -0
- groundly-0.3.0/.gitignore +19 -0
- groundly-0.3.0/CLAUDE.md +15 -0
- groundly-0.3.0/LICENSE +21 -0
- groundly-0.3.0/PKG-INFO +88 -0
- groundly-0.3.0/README.md +38 -0
- groundly-0.3.0/docs/architecture/agents.md +56 -0
- groundly-0.3.0/docs/architecture/data-model.md +69 -0
- groundly-0.3.0/docs/architecture/overview.md +53 -0
- groundly-0.3.0/docs/architecture/retrieval.md +62 -0
- groundly-0.3.0/docs/design/DESIGN.md +159 -0
- groundly-0.3.0/docs/design/course upload/DESIGN.md +159 -0
- groundly-0.3.0/docs/design/course upload/code.html +464 -0
- groundly-0.3.0/docs/design/course upload/screen.png +0 -0
- groundly-0.3.0/docs/design/home/DESIGN.md +159 -0
- groundly-0.3.0/docs/design/home/code.html +527 -0
- groundly-0.3.0/docs/design/home/screen.png +0 -0
- groundly-0.3.0/docs/design/knowledge base/DESIGN.md +159 -0
- groundly-0.3.0/docs/design/knowledge base/code.html +433 -0
- groundly-0.3.0/docs/design/knowledge base/screen.png +0 -0
- groundly-0.3.0/docs/design/landing/DESIGN.md +159 -0
- groundly-0.3.0/docs/design/landing/code.html +314 -0
- groundly-0.3.0/docs/design/landing/screen.png +0 -0
- groundly-0.3.0/docs/groundly-spec.md +158 -0
- groundly-0.3.0/docs/infrastructure/cost-model.md +26 -0
- groundly-0.3.0/docs/infrastructure/distribution.md +34 -0
- groundly-0.3.0/docs/infrastructure/security.md +40 -0
- groundly-0.3.0/docs/superpowers/reviews/2026-07-16-p1-ingestion-pipeline-review.md +121 -0
- groundly-0.3.0/docs/superpowers/reviews/2026-07-16-p1-ingestion-pipeline-round2-review.md +149 -0
- groundly-0.3.0/docs/superpowers/specs/2026-07-16-p1-cli-surface-design.md +112 -0
- groundly-0.3.0/docs/superpowers/specs/2026-07-16-p1-ingestion-pipeline.md +84 -0
- groundly-0.3.0/docs/tech-stack/tech-stack.md +50 -0
- groundly-0.3.0/docs/use-cases/knowledge-base.md +73 -0
- groundly-0.3.0/docs/use-cases/sharing.md +28 -0
- groundly-0.3.0/docs/use-cases/student-modes.md +70 -0
- groundly-0.3.0/groundly/__init__.py +0 -0
- groundly-0.3.0/groundly/agents/__init__.py +0 -0
- groundly-0.3.0/groundly/cli/__init__.py +261 -0
- groundly-0.3.0/groundly/core/__init__.py +0 -0
- groundly-0.3.0/groundly/core/manifest.py +76 -0
- groundly-0.3.0/groundly/core/paths.py +33 -0
- groundly-0.3.0/groundly/core/store.py +143 -0
- groundly-0.3.0/groundly/core/subject.py +44 -0
- groundly-0.3.0/groundly/ingestion/__init__.py +0 -0
- groundly-0.3.0/groundly/ingestion/extract.py +89 -0
- groundly-0.3.0/groundly/ingestion/extract_worker.py +126 -0
- groundly-0.3.0/groundly/ingestion/pipeline.py +210 -0
- groundly-0.3.0/groundly/llm/__init__.py +0 -0
- groundly-0.3.0/groundly/llm/embeddings.py +62 -0
- groundly-0.3.0/groundly/mcp/__init__.py +0 -0
- groundly-0.3.0/groundly/retrieval/__init__.py +0 -0
- groundly-0.3.0/groundly/web/__init__.py +0 -0
- groundly-0.3.0/groundly/web/static/theme.css +22 -0
- groundly-0.3.0/pyproject.toml +56 -0
- groundly-0.3.0/tests/__init__.py +0 -0
- groundly-0.3.0/tests/test_cli.py +210 -0
- groundly-0.3.0/tests/test_paths.py +36 -0
- groundly-0.3.0/tests/test_pipeline.py +293 -0
- groundly-0.3.0/tests/test_slow_models.py +19 -0
- groundly-0.3.0/tests/test_store.py +100 -0
- groundly-0.3.0/unilearn/cli/__init__.py +261 -0
- groundly-0.3.0/unilearn/core/manifest.py +76 -0
- groundly-0.3.0/unilearn/core/paths.py +33 -0
- groundly-0.3.0/unilearn/core/store.py +143 -0
- groundly-0.3.0/unilearn/core/subject.py +44 -0
- groundly-0.3.0/unilearn/ingestion/extract.py +89 -0
- groundly-0.3.0/unilearn/ingestion/extract_worker.py +126 -0
- groundly-0.3.0/unilearn/ingestion/pipeline.py +210 -0
- groundly-0.3.0/unilearn/llm/embeddings.py +62 -0
- groundly-0.3.0/uv.lock +5392 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: adversarial-reviewer
|
|
3
|
+
description: Fresh-context adversarial review of a completed task's code. Spawn when a task/feature is done, before Paul commits. Assumes the code is guilty until proven correct — hunts real bugs, broken edge cases, and untested claims; ignores style. Writes its review to docs/superpowers/reviews/.
|
|
4
|
+
tools: Read, Grep, Glob, Bash, Write
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
You are an adversarial reviewer for Groundly. You arrive with zero context from the
|
|
8
|
+
session that wrote the code — that is the point. Do not trust the author's summary,
|
|
9
|
+
comments, or test names; trust only what you can read and run.
|
|
10
|
+
|
|
11
|
+
## Procedure
|
|
12
|
+
|
|
13
|
+
1. Get the change set: `git diff` (+ `git status --short` for untracked files; read those
|
|
14
|
+
whole). If a range or file list is in your prompt, use that instead.
|
|
15
|
+
2. Read the contracts the change claims to satisfy: the relevant `docs/use-cases/`
|
|
16
|
+
acceptance criteria and `.claude/rules/`. The docs are the source of truth.
|
|
17
|
+
3. Attack the code. For every function ask: what input, state, or timing breaks this?
|
|
18
|
+
Priorities, in order:
|
|
19
|
+
- **Correctness**: off-by-one, wrong SQL, race between processes (CLI + MCP share the
|
|
20
|
+
DBs), transaction boundaries that don't cover what the comment claims, error paths
|
|
21
|
+
that leave partial state (files copied but rows not written, and vice versa).
|
|
22
|
+
- **Edge cases**: empty inputs, unicode filenames, huge files, duplicate names,
|
|
23
|
+
interrupted runs, concurrent runs of the same command.
|
|
24
|
+
- **Lying tests**: tests that assert the mock instead of the behavior, happy-path-only
|
|
25
|
+
coverage, acceptance criteria with no test at all.
|
|
26
|
+
- **Silent failures**: swallowed exceptions, `except Exception` hiding real errors,
|
|
27
|
+
failure states that report success.
|
|
28
|
+
4. Verify suspicions cheaply where possible: run `uv run pytest -q`, or a targeted
|
|
29
|
+
`uv run python -c ...` reproduction. A confirmed bug outranks ten hypotheticals.
|
|
30
|
+
5. Write the review to `docs/superpowers/reviews/YYYY-MM-DD-<topic>-review.md`
|
|
31
|
+
(create the directory if needed). Do not fix anything; do not commit.
|
|
32
|
+
|
|
33
|
+
## Review file format
|
|
34
|
+
|
|
35
|
+
```markdown
|
|
36
|
+
# Adversarial review: <topic> (<date>)
|
|
37
|
+
|
|
38
|
+
Verdict: BLOCK | MERGE WITH FIXES | MERGE
|
|
39
|
+
|
|
40
|
+
## Findings
|
|
41
|
+
### F1 — <one-line defect> [severity: high|medium|low]
|
|
42
|
+
- Where: file:line
|
|
43
|
+
- Failure scenario: concrete input/state → wrong outcome
|
|
44
|
+
- Evidence: what you ran or read that confirms it (or "unverified — plausible")
|
|
45
|
+
|
|
46
|
+
## What I tried and could not break
|
|
47
|
+
<one line each — so the next reviewer doesn't re-cover the same ground>
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Rank findings by severity. A finding needs a concrete failure scenario — "could be
|
|
51
|
+
cleaner" is not a finding. If you find nothing real, say so plainly; do not invent
|
|
52
|
+
issues to look thorough. End your reply to the caller with the verdict line and the
|
|
53
|
+
review file path.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: security-reviewer
|
|
3
|
+
description: Reviews Groundly changes against the project's threat model — import trust boundary (zip-slip, hostile bundles), prompt injection via documents/imports, subprocess execution, local server exposure, privacy/export boundary. Use for changes touching import/export, prompt assembly, the verifier runner, serve, or before a phase gate.
|
|
4
|
+
tools: Read, Grep, Glob, Bash
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
You are Groundly's security reviewer. The authoritative threat model is `docs/infrastructure/security.md` — a single-user local tool whose risks are import bundles, document injection, subprocess execution, local servers, and the export privacy boundary. Review against *that* model, not a generic OWASP list; there is no auth, no tenancy, no upload pipeline.
|
|
8
|
+
|
|
9
|
+
## Procedure
|
|
10
|
+
|
|
11
|
+
1. Get the change set (`git diff`, or files named in your prompt).
|
|
12
|
+
2. Work the checklist, highest exposure first. Read `docs/infrastructure/security.md` for the authoritative control when unsure.
|
|
13
|
+
3. Findings need a concrete path — no theoretical hand-waving.
|
|
14
|
+
|
|
15
|
+
## Threat checklist (project-specific)
|
|
16
|
+
|
|
17
|
+
**1. Import (the trust boundary)**
|
|
18
|
+
Extraction must reject path-escaping entries and symlinks; manifest and `PRAGMA user_version` validated *before* content is used; imported SQLite never trusted beyond schema checks; imported chunks/summaries/profiles handled as layer-4 (profiles: size cap + no authority). Import must never touch the existing `progress.db` or overwrite a subject without confirmation.
|
|
19
|
+
|
|
20
|
+
**2. Prompt injection via content**
|
|
21
|
+
All retrieved/imported/recalled content delimited as data in prompts; nothing from layer 4 or layer 2 can alter grounding/citation/refusal behavior. Watch new prompt-assembly code and new tool outputs fed back into prompts.
|
|
22
|
+
|
|
23
|
+
**3. Subprocess runner (verifier, challenges)**
|
|
24
|
+
Timeout, temp working dir, output size cap, argv exec (no shell interpolation of generated strings). No claim of sandboxing where none exists — docs state self-risk honestly.
|
|
25
|
+
|
|
26
|
+
**4. Local servers**
|
|
27
|
+
`serve` binds 127.0.0.1 only; no auth is acceptable *only* on loopback; any change loosening the bind or adding network surface is a finding. stdio MCP must not open sockets.
|
|
28
|
+
|
|
29
|
+
**5. Privacy / export boundary**
|
|
30
|
+
Export code reading `progress.db` (traces contain every query the student asked); telemetry or third-party calls beyond the configured provider + HF downloads; secrets/keys appearing in traces, exports, or logs; export UX losing the "contains everything indexed" statement.
|
|
31
|
+
|
|
32
|
+
## Output format
|
|
33
|
+
|
|
34
|
+
One finding per line: `SEVERITY file:line — attack enabled — weakened control (doc §)`. Severities: `CRITICAL` (exploitable now), `HIGH` (one step away), `NOTE`. End with a one-line verdict; if clean, name the top residual risk to watch.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spec-guardian
|
|
3
|
+
description: Reviews Groundly code changes against the documented architecture invariants — module layering, LLM provider boundary, grounding/citation guarantees, verifier gate, storage/concurrency rules. Use after implementing a feature, before Paul commits, or when asked whether code matches the docs.
|
|
4
|
+
tools: Read, Grep, Glob, Bash
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
You are the spec guardian for Groundly (local-first, MCP-first). Your only job: find where a change violates the documented architecture, or where the docs have gone stale relative to the code. No style or generic-quality review.
|
|
8
|
+
|
|
9
|
+
## Procedure
|
|
10
|
+
|
|
11
|
+
1. Get the change set (`git diff` / `git diff --staged`, or files named in your prompt).
|
|
12
|
+
2. Check the checklist against the diff. Authoritative rules: `.claude/rules/architecture.md`, `docs/architecture/overview.md`, `docs/architecture/data-model.md`.
|
|
13
|
+
3. Report only violations and doc drift, each with file:line, the rule broken, and the doc stating it. If clean, say so in one line.
|
|
14
|
+
|
|
15
|
+
## Checklist
|
|
16
|
+
|
|
17
|
+
**Provider boundary** — LLM client construction or provider SDK usage outside `groundly/llm/`? Hardcoded model/base_url/key? An LLM call path that bypasses `llm/` (and therefore trace cost recording)? A feature that breaks zero-key operation for index/search/submit_* paths?
|
|
18
|
+
|
|
19
|
+
**Module layering** — anything importing `cli/`, `mcp/`, or `web/` from below? `retrieval` importing `agents`? `ingestion` serving a query path?
|
|
20
|
+
|
|
21
|
+
**Grounding** — any generation path returning content without resolvable chunk-id citations? Fallback to model knowledge on empty retrieval (must be "not covered")? A community summary used as a citation target?
|
|
22
|
+
|
|
23
|
+
**Verifier gate** — any write into decks/questions that skips verification (either path)? Code answers accepted without subprocess execution? Missing generation-source recording?
|
|
24
|
+
|
|
25
|
+
**Storage & concurrency** — SQLite connections without WAL + busy_timeout? Model loading at MCP spawn instead of lazily? `serve` binding non-loopback? Schema change without a `user_version` bump? Export code touching `progress.db`?
|
|
26
|
+
|
|
27
|
+
**Trust layers** — prompt assembly interpolating retrieved/imported content or notes outside the delimited layer-4 slot? Subject-profile content able to alter grounding rules? Import path missing manifest validation or zip-slip protection?
|
|
28
|
+
|
|
29
|
+
**Doc drift** — does the change alter behavior a doc states (spec §4/§7, use-case acceptance criteria, interchange format)? Flag the doc; don't edit it yourself.
|
|
30
|
+
|
|
31
|
+
## Output format
|
|
32
|
+
|
|
33
|
+
One line per finding: `SEVERITY file:line — rule broken — doc reference`. Severities: `BLOCK` (invariant violated), `DRIFT` (docs stale), `NOTE` (judgment call). End with a one-line verdict.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Architecture invariants
|
|
2
|
+
|
|
3
|
+
Source of truth: `docs/architecture/overview.md`. Violating these is a bug even if tests pass.
|
|
4
|
+
|
|
5
|
+
## Module boundaries (`groundly/`)
|
|
6
|
+
|
|
7
|
+
Layers: clients (`cli/`, `mcp/`, `web/`) → services (`agents/`, `retrieval/`, `ingestion/`) → foundations (`llm/`, `core/`).
|
|
8
|
+
|
|
9
|
+
- Dependencies point one way; **nothing imports the client layer**.
|
|
10
|
+
- `agents` may call `retrieval` (as a tool) and the subprocess runner; `retrieval` never calls `agents`.
|
|
11
|
+
- `ingestion` writes the stores; it never serves queries.
|
|
12
|
+
|
|
13
|
+
## LLM provider boundary (hard rule)
|
|
14
|
+
|
|
15
|
+
- LLM clients are constructed **only** in `groundly/llm/` — OpenAI-compatible `base_url` + model + key, **per call class** (`chat`, `generation`, `extraction`, `router`) from `~/.groundly/config.toml`. Never hardcode a provider; cloud keys and LM Studio/Ollama are the same code path.
|
|
16
|
+
- Every LLM call passes through `llm/` and records tokens + cost into the traces table.
|
|
17
|
+
- **Zero-key operation is first-class**: index, `search`, thin `submit_*` generation must never require a provider.
|
|
18
|
+
- Embeddings: `bge-m3`, pinned incl. hf_revision — the pin is the interchange compatibility contract. Changing it = full re-index migration + manifest bump, never a tweak.
|
|
19
|
+
|
|
20
|
+
## Storage & concurrency
|
|
21
|
+
|
|
22
|
+
- SQLite **WAL + busy_timeout on every connection** (one-shot CLI and host-spawned MCP share store.db); schema via `PRAGMA user_version`, no migration framework.
|
|
23
|
+
- **Lazy model loading** — never load bge-m3/reranker at MCP spawn; load on first use.
|
|
24
|
+
- `groundly serve` binds **127.0.0.1 only**.
|
|
25
|
+
- Generation jobs are serialized when the provider is a local runtime; never block a request handler on an agent loop.
|
|
26
|
+
|
|
27
|
+
## Frameworks
|
|
28
|
+
|
|
29
|
+
Exactly three, one owner each: LlamaIndex (retrieval interface), MS graphrag (graph backend), FastMCP (tool surface). Agent loops are plain bounded async functions — no LangGraph. Exact pins for graphrag/llama-index/docling/sentence-transformers/FlagEmbedding set at P1; upgrades are deliberate events recorded in docs + manifest.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Conventions
|
|
2
|
+
|
|
3
|
+
## Docs are the source of truth
|
|
4
|
+
|
|
5
|
+
- Decisions live in `docs/groundly-spec.md` §4/§7 with satellite docs; a changed decision updates the docs in the same change set (`/decision`).
|
|
6
|
+
- "Done" for a feature = the acceptance criteria in `docs/use-cases/` pass.
|
|
7
|
+
|
|
8
|
+
## Python
|
|
9
|
+
|
|
10
|
+
- Python ≥3.11; typer CLI; FastAPI only inside `groundly serve`; Pydantic v2 + pydantic-settings; type hints on public functions.
|
|
11
|
+
- SQLite schema versioned via `PRAGMA user_version` (checked on open; refuse newer-than-known). Integrity rules as constraints where SQLite allows (unique hashes, FKs), not app code.
|
|
12
|
+
- pytest for tests (no service containers — SQLite files + stub providers); ruff for lint + format.
|
|
13
|
+
- Pin `graphrag`, `llama-index`, `docling`, `sentence-transformers`, `FlagEmbedding` exactly at P1 start; record pins in thesis + export manifest.
|
|
14
|
+
|
|
15
|
+
## Product surfaces
|
|
16
|
+
|
|
17
|
+
- MCP tools are the product surface: tool descriptions are UX — write them for the host model. Citations double as MCP resources (`groundly://<subject>/<file>#page=N`).
|
|
18
|
+
- CLI verbs are batch lifecycle only (index/import/export/config/ask); anything conversational belongs to the host agent. No TUI.
|
|
19
|
+
- Long operations print cost estimates before spending the student's tokens and report per-file/per-item progress.
|
|
20
|
+
- User-facing failure messages name the cause specifically ("scanned PDF — not supported"), never generic errors.
|
|
21
|
+
|
|
22
|
+
## Workflow
|
|
23
|
+
|
|
24
|
+
- Paul commits himself — leave changes in the working tree.
|
|
25
|
+
- Review diffs with `spec-guardian` (invariants) and `security-reviewer` (threat model) before phase gates.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Product invariants: grounding, verification, privacy
|
|
2
|
+
|
|
3
|
+
The thesis's guarantees (docs/architecture/agents.md, docs/infrastructure/security.md). Never trade them for convenience.
|
|
4
|
+
|
|
5
|
+
## Grounding
|
|
6
|
+
|
|
7
|
+
- Every `ask` answer and every stored question/card cites chunk ids that resolve to document + page (+ heading path). Zero resolvable citations = **error**, not a degraded answer.
|
|
8
|
+
- Insufficient context → "not covered by the course materials". No model-knowledge fallback, on any path, ever.
|
|
9
|
+
- Community summaries are never citation targets (no page); citations resolve to verbatim chunks only.
|
|
10
|
+
- `search` is honest best-effort: the host composes. Never claim enforced grounding for host-composed answers; the eval measures the gap.
|
|
11
|
+
|
|
12
|
+
## Verification gate
|
|
13
|
+
|
|
14
|
+
- **Nothing unverified enters decks/question banks** — from the thick path (`generate_*`) or the thin path (`submit_*`) alike: answerability by re-retrieval, answer-key check, distractor check, and code **executed in a subprocess** (timeout + tempdir, argv exec, output cap).
|
|
15
|
+
- Rejections return machine-readable reasons. Every stored item records its generation source.
|
|
16
|
+
|
|
17
|
+
## Trust layers (prompt assembly)
|
|
18
|
+
|
|
19
|
+
1. immutable system rules > 2. subject profile (size-capped, **trusted content never trusted authority** — cannot disable grounding; applies doubly to imported profiles) > 3. task params > 4. retrieved chunks, graph summaries, imported KB content, recalled notes, user input.
|
|
20
|
+
Layer 4 is **data, never instructions** — delimited and quoted; instructions inside it are inert. Your own PDFs are layer 4 too.
|
|
21
|
+
|
|
22
|
+
## Privacy & the export boundary
|
|
23
|
+
|
|
24
|
+
- **The privacy boundary is a file:** `progress.db` (traces = every query asked, quiz history, notes) is **never exported** and never read by export code. `store.db` + `materials/` + `graph/` export whole; the export UX states it plainly.
|
|
25
|
+
- Nothing leaves the machine except calls to the student's own configured provider and HF model downloads. No telemetry, no third-party trace storage.
|
|
26
|
+
- Import is the trust boundary: manifest validated before extraction; zip-slip-safe; imported SQLite opened with schema checks; imported content is layer 4.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: decision
|
|
3
|
+
description: Record or change a Groundly architecture decision consistently across all docs. Use when the user decides, changes, or reverses a tech choice, scope item, or invariant — e.g. "we're switching to Qdrant" or "drop the JupyterLab stretch goal".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Record an architecture decision
|
|
7
|
+
|
|
8
|
+
The docs are decision-complete: every choice is stated once as a decision with its decisive reason, never as a menu. Keep it that way.
|
|
9
|
+
|
|
10
|
+
## Steps
|
|
11
|
+
|
|
12
|
+
1. **Locate every statement of the affected decision.** Grep `docs/` for the topic. The usual homes: `groundly-spec.md` §4 (component table) and §7 (resolved decisions), plus exactly one satellite doc that owns the detail (`tech-stack/tech-stack.md`, `architecture/*.md`, or `infrastructure/*.md`). Check `.claude/rules/` too — invariants live there in condensed form.
|
|
13
|
+
|
|
14
|
+
2. **Capture the why.** A decision entry needs: the choice, the decisive reason, and consequences (cost, privacy, migration path). If the user gave no reason, ask for one — "changed our minds" is not auditable in a thesis.
|
|
15
|
+
|
|
16
|
+
3. **Update all statements in one pass.** Spec table row, spec §7 entry, the owning satellite doc, and any rule file. The old choice becomes the documented alternative/migration path if it remains viable; delete it otherwise.
|
|
17
|
+
|
|
18
|
+
4. **Check for cascade effects.** Does the change alter the cost model (`infrastructure/cost-model.md`), the distribution story (`infrastructure/distribution.md`), the threat model (`infrastructure/security.md`), the interchange format (`architecture/data-model.md` — a manifest/pin change breaks import compatibility), or an acceptance criterion? Update those too or explicitly note why they're unaffected.
|
|
19
|
+
|
|
20
|
+
5. **Update project memory** (`groundly-architecture-decisions` memory file) so future sessions treat the new decision as settled.
|
|
21
|
+
|
|
22
|
+
6. **Report** the changed files and the one-line form of the new decision.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: implement-uc
|
|
3
|
+
description: Implement a Groundly use case (UC-XX) driven by its documented acceptance criteria. Use when starting work on any use case from docs/use-cases/, e.g. "/implement-uc UC-02" or "let's build the mock test generator".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Implement a use case
|
|
7
|
+
|
|
8
|
+
Input: a UC id (UC-01…UC-30) or feature name. The acceptance criteria in `docs/use-cases/` define "done" — not vibes.
|
|
9
|
+
|
|
10
|
+
## Steps
|
|
11
|
+
|
|
12
|
+
1. **Load the contract.** Read the UC's section in `docs/use-cases/` (knowledge-base / student-modes / sharing). Extract: preconditions, main flow, alternate/error flows, acceptance criteria. Read the referenced architecture docs for the parts this UC touches (`overview.md` for module placement, `data-model.md` for storage + interchange, `retrieval.md`/`agents.md` if applicable).
|
|
13
|
+
|
|
14
|
+
2. **Check phase order.** Spec §8 maps UCs to phases P1–P7. If this UC depends on machinery from an earlier phase that doesn't exist yet (e.g., UC-12 graph formats need the P5 graph; UC-14 mastery needs P5 communities), say so and confirm scope before coding.
|
|
15
|
+
|
|
16
|
+
3. **Restate criteria as a test list.** Each acceptance criterion and each alternate flow becomes at least one named test. Include the standing invariant tests that apply (citation resolution for anything generating content; verifier gate for anything writing decks/questions; export-boundary test for anything touching progress.db or export).
|
|
17
|
+
|
|
18
|
+
4. **Implement inside the module boundaries** (`.claude/rules/architecture.md`): client surface in `cli/`/`mcp/`, logic in the owning service module, LLM access only via `groundly/llm/`, long work as background tasks behind a job id. Tests first where the logic is non-trivial; tests use SQLite files + stub providers, no services.
|
|
19
|
+
|
|
20
|
+
5. **Verify.** Run the test list; every acceptance criterion must map to a passing test. Report the mapping explicitly (criterion → test name → pass/fail).
|
|
21
|
+
|
|
22
|
+
6. **Close the loop.** If implementation forced a deviation from the documented flow, update the UC doc in the same change set and say why. Consider running the `spec-guardian` agent on the diff before finishing.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, "**"]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
server:
|
|
11
|
+
name: groundly
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- uses: astral-sh/setup-uv@v5
|
|
18
|
+
with:
|
|
19
|
+
enable-cache: true
|
|
20
|
+
|
|
21
|
+
- name: Install dependencies
|
|
22
|
+
run: uv sync --extra dev
|
|
23
|
+
|
|
24
|
+
- name: Lint (ruff check)
|
|
25
|
+
run: uv run ruff check .
|
|
26
|
+
|
|
27
|
+
- name: Format check (ruff format)
|
|
28
|
+
run: uv run ruff format --check .
|
|
29
|
+
|
|
30
|
+
- name: Test (pytest)
|
|
31
|
+
run: uv run pytest
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
name: Publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: ["v*"]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
publish:
|
|
9
|
+
name: Build and publish to PyPI
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
environment: pypi
|
|
12
|
+
permissions:
|
|
13
|
+
id-token: write
|
|
14
|
+
contents: read
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- uses: astral-sh/setup-uv@v5
|
|
20
|
+
with:
|
|
21
|
+
enable-cache: true
|
|
22
|
+
|
|
23
|
+
- name: Install dependencies
|
|
24
|
+
run: uv sync --extra dev
|
|
25
|
+
|
|
26
|
+
- name: Lint (ruff check)
|
|
27
|
+
run: uv run ruff check .
|
|
28
|
+
|
|
29
|
+
- name: Format check (ruff format)
|
|
30
|
+
run: uv run ruff format --check .
|
|
31
|
+
|
|
32
|
+
- name: Test (pytest)
|
|
33
|
+
run: uv run pytest
|
|
34
|
+
|
|
35
|
+
- name: Build
|
|
36
|
+
run: uv build
|
|
37
|
+
|
|
38
|
+
- name: Publish
|
|
39
|
+
run: uv publish
|
groundly-0.3.0/CLAUDE.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Groundly
|
|
2
|
+
|
|
3
|
+
Local-first course knowledge bases for AI agents — index course materials, serve them to MCP hosts (Claude Code/Codex/Desktop) with enforced grounding, verified generation, and a portable interchange format. Bachelor thesis project. Pitch and status: [README.md](README.md).
|
|
4
|
+
|
|
5
|
+
## Where things are decided
|
|
6
|
+
|
|
7
|
+
- **Master spec + document map:** [docs/groundly-spec.md](docs/groundly-spec.md) — §4 component decisions, §7 decision register, §8 phasing (P1–P7).
|
|
8
|
+
- **Use-case contracts (acceptance criteria = "done"):** [docs/use-cases/](docs/use-cases/knowledge-base.md)
|
|
9
|
+
- **Architecture:** [overview](docs/architecture/overview.md) · [data-model + interchange](docs/architecture/data-model.md) · [retrieval](docs/architecture/retrieval.md) · [agents](docs/architecture/agents.md)
|
|
10
|
+
- **Stack + LLM provider boundary:** [docs/tech-stack/tech-stack.md](docs/tech-stack/tech-stack.md)
|
|
11
|
+
- **Distribution / security / costs:** [docs/infrastructure/](docs/infrastructure/distribution.md)
|
|
12
|
+
|
|
13
|
+
## Working rules
|
|
14
|
+
|
|
15
|
+
Binding invariants auto-load from `.claude/rules/` (module boundaries, grounding guarantees, conventions). Docs are the source of truth — a decision change updates the docs in the same change set (use `/decision`). Implement use cases with `/implement-uc UC-XX`; review with the `spec-guardian` and `security-reviewer` agents. Developer commits himself — leave changes in the working tree for review.
|
groundly-0.3.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Paul Hondola
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
groundly-0.3.0/PKG-INFO
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: groundly
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Local-first course knowledge bases for AI agents: index your materials, study grounded, share the index.
|
|
5
|
+
License: MIT License
|
|
6
|
+
|
|
7
|
+
Copyright (c) 2026 Paul Hondola
|
|
8
|
+
|
|
9
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
10
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
11
|
+
in the Software without restriction, including without limitation the rights
|
|
12
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
13
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
14
|
+
furnished to do so, subject to the following conditions:
|
|
15
|
+
|
|
16
|
+
The above copyright notice and this permission notice shall be included in all
|
|
17
|
+
copies or substantial portions of the Software.
|
|
18
|
+
|
|
19
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
20
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
21
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
22
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
23
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
24
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
25
|
+
SOFTWARE.
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Python: <3.13,>=3.11
|
|
28
|
+
Requires-Dist: docling==2.113.0
|
|
29
|
+
Requires-Dist: fastapi>=0.111
|
|
30
|
+
Requires-Dist: fastmcp>=2.0
|
|
31
|
+
Requires-Dist: flagembedding==1.3.5
|
|
32
|
+
Requires-Dist: genanki>=0.13
|
|
33
|
+
Requires-Dist: graphrag==3.1.0
|
|
34
|
+
Requires-Dist: httpx>=0.27
|
|
35
|
+
Requires-Dist: llama-index==0.14.23
|
|
36
|
+
Requires-Dist: pydantic-settings>=2.3
|
|
37
|
+
Requires-Dist: pydantic>=2.7
|
|
38
|
+
Requires-Dist: rich>=13
|
|
39
|
+
Requires-Dist: sentence-transformers==5.6.0
|
|
40
|
+
Requires-Dist: sqlite-vec>=0.1
|
|
41
|
+
Requires-Dist: typer>=0.12
|
|
42
|
+
Requires-Dist: uvicorn>=0.30
|
|
43
|
+
Provides-Extra: dev
|
|
44
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
45
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
46
|
+
Requires-Dist: ruff>=0.5; extra == 'dev'
|
|
47
|
+
Provides-Extra: eval
|
|
48
|
+
Requires-Dist: ragas>=0.2; extra == 'eval'
|
|
49
|
+
Description-Content-Type: text/markdown
|
|
50
|
+
|
|
51
|
+
# Groundly
|
|
52
|
+
|
|
53
|
+
**Local-first course knowledge bases for AI agents.** Index your course materials once; then any MCP-capable agent — Claude Code, Claude Desktop, Codex — can answer questions grounded in the actual course content with page-level citations, generate execution-verified tests and flashcards, quiz your weak areas, and track your mastery. Share the finished knowledge base with your coursemates as a single file.
|
|
54
|
+
|
|
55
|
+
Bachelor thesis project, Universitatea Politehnica Timișoara.
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
$ groundly index <SUBJECT> ./slides/
|
|
59
|
+
✓ 12 PDFs → 384 chunks → embedded (bge-m3, local) → indexed
|
|
60
|
+
$ # wire into Claude Code: { "command": "groundly", "args": ["mcp"] }
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Then, inside your agent: *"What did lecture 4 say about deadlock prevention?"* → answer cited to **lecture-04.pdf, page 12, "Deadlocks › Prevention"** — or *"not covered by the course materials"*, never a hallucination.
|
|
64
|
+
|
|
65
|
+
## Why not NotebookLM / a Claude Project?
|
|
66
|
+
|
|
67
|
+
1. **Verified generation** — every test question and flashcard passes a verifier: answerable from the cited sources, answer key checked, and code questions' reference solutions **actually executed** before acceptance.
|
|
68
|
+
2. **Enforced citations** — structural, page-level, with honest refusal when the corpus doesn't cover it.
|
|
69
|
+
3. **A portable index** — `groundly export <SUBJECT>` → one file; a coursemate imports it and their agent uses it directly. The expensive artifacts (knowledge graph, verified decks) are built once and shared.
|
|
70
|
+
4. **Cross-host progress** — mastery per topic and study memory persist in local files, whatever agent you talk to. Your queries and results never leave your machine and are never part of an export.
|
|
71
|
+
|
|
72
|
+
## Features
|
|
73
|
+
|
|
74
|
+
- **Grounded Q&A** — hybrid retrieval (bge-m3 dense + learned sparse + BM25, reranked; optional GraphRAG for synthesis questions), via MCP tools or `groundly ask`
|
|
75
|
+
- **Verified quizzes & coding challenges** — generated by Groundly (your API key) *or by your agent* (no key needed) — either way, nothing unverified is stored
|
|
76
|
+
- **Flashcards → Anki** — verified decks exported as `.apkg`
|
|
77
|
+
- **Mastery map & study memory** — per-topic mastery from quiz results; "continue studying" warm starts in any host
|
|
78
|
+
- **Import/export** — the whole knowledge base as one shareable file, with pinned-model compatibility
|
|
79
|
+
|
|
80
|
+
## Install
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
uv tool install groundly
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Local-first honestly stated: first run downloads the embedding models (~2.7GB total). Indexing and search need **no API key**; grounded answer generation and graph builds use your own OpenAI-compatible provider (cloud key, LM Studio, or Ollama).
|
|
87
|
+
|
|
88
|
+
**Thesis core:** four-arm RAG vs GraphRAG evaluation on real RO/EN course corpora, plus a measured comparison of enforced vs agent-mediated grounding.
|
groundly-0.3.0/README.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Groundly
|
|
2
|
+
|
|
3
|
+
**Local-first course knowledge bases for AI agents.** Index your course materials once; then any MCP-capable agent — Claude Code, Claude Desktop, Codex — can answer questions grounded in the actual course content with page-level citations, generate execution-verified tests and flashcards, quiz your weak areas, and track your mastery. Share the finished knowledge base with your coursemates as a single file.
|
|
4
|
+
|
|
5
|
+
Bachelor thesis project, Universitatea Politehnica Timișoara.
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
$ groundly index <SUBJECT> ./slides/
|
|
9
|
+
✓ 12 PDFs → 384 chunks → embedded (bge-m3, local) → indexed
|
|
10
|
+
$ # wire into Claude Code: { "command": "groundly", "args": ["mcp"] }
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Then, inside your agent: *"What did lecture 4 say about deadlock prevention?"* → answer cited to **lecture-04.pdf, page 12, "Deadlocks › Prevention"** — or *"not covered by the course materials"*, never a hallucination.
|
|
14
|
+
|
|
15
|
+
## Why not NotebookLM / a Claude Project?
|
|
16
|
+
|
|
17
|
+
1. **Verified generation** — every test question and flashcard passes a verifier: answerable from the cited sources, answer key checked, and code questions' reference solutions **actually executed** before acceptance.
|
|
18
|
+
2. **Enforced citations** — structural, page-level, with honest refusal when the corpus doesn't cover it.
|
|
19
|
+
3. **A portable index** — `groundly export <SUBJECT>` → one file; a coursemate imports it and their agent uses it directly. The expensive artifacts (knowledge graph, verified decks) are built once and shared.
|
|
20
|
+
4. **Cross-host progress** — mastery per topic and study memory persist in local files, whatever agent you talk to. Your queries and results never leave your machine and are never part of an export.
|
|
21
|
+
|
|
22
|
+
## Features
|
|
23
|
+
|
|
24
|
+
- **Grounded Q&A** — hybrid retrieval (bge-m3 dense + learned sparse + BM25, reranked; optional GraphRAG for synthesis questions), via MCP tools or `groundly ask`
|
|
25
|
+
- **Verified quizzes & coding challenges** — generated by Groundly (your API key) *or by your agent* (no key needed) — either way, nothing unverified is stored
|
|
26
|
+
- **Flashcards → Anki** — verified decks exported as `.apkg`
|
|
27
|
+
- **Mastery map & study memory** — per-topic mastery from quiz results; "continue studying" warm starts in any host
|
|
28
|
+
- **Import/export** — the whole knowledge base as one shareable file, with pinned-model compatibility
|
|
29
|
+
|
|
30
|
+
## Install
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
uv tool install groundly
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Local-first honestly stated: first run downloads the embedding models (~2.7GB total). Indexing and search need **no API key**; grounded answer generation and graph builds use your own OpenAI-compatible provider (cloud key, LM Studio, or Ollama).
|
|
37
|
+
|
|
38
|
+
**Thesis core:** four-arm RAG vs GraphRAG evaluation on real RO/EN course corpora, plus a measured comparison of enforced vs agent-mediated grounding.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Agent Layer
|
|
2
|
+
|
|
3
|
+
Expands [`groundly-spec.md`](../groundly-spec.md) §5b. Governing rule: **agents only where the system must decide, iterate, or use tools mid-task** — everything else is a pipeline. Specialization is data, never code: "which subject" is literally which `~/.groundly/<SUBJECT>/` directory is open. Loops are **plain bounded async functions** — LangGraph was dropped when the roster shrank (consolidation pass).
|
|
4
|
+
|
|
5
|
+
## The roster (two)
|
|
6
|
+
|
|
7
|
+
### 1. Ask pipeline — interactive
|
|
8
|
+
|
|
9
|
+
`router → retrieval arm(s) → fusion/rerank → trust-layered prompt assembly → generation (chat call class) → citation resolution → cited answer or "not covered" → trace row.`
|
|
10
|
+
|
|
11
|
+
Exposed identically as the MCP `ask` tool and the `groundly ask` CLI verb — **the product tool and the evaluation instrument are one function**. Grounding is enforced inside this boundary: a response with zero resolvable citations is an error; insufficient context returns the refusal, never model knowledge.
|
|
12
|
+
|
|
13
|
+
Honest scope note: host agents may prefer raw `search` (free, composable) and compose their own answers — that path is best-effort grounding by construction, and the eval *measures* the gap (grounding-fidelity experiment) rather than pretending it away.
|
|
14
|
+
|
|
15
|
+
### 2. Exam verifier — the identity of generation
|
|
16
|
+
|
|
17
|
+
Generation is pluggable; **verification is not**. Every question/card entering `store.db` passes, per type:
|
|
18
|
+
|
|
19
|
+
- **All types:** answerable from the cited chunks alone (confirmed by re-retrieval); answer key correct; distractors actually wrong (MCQ).
|
|
20
|
+
- **Code questions (incl. UC-13 challenges):** the reference solution is **executed in a subprocess** (timeout, tempdir) — compile + run + output matches. A hard guarantee, not an LLM opinion.
|
|
21
|
+
|
|
22
|
+
Two doors, one gate:
|
|
23
|
+
|
|
24
|
+
| Path | Generator | Needs API key | Loop |
|
|
25
|
+
|---|---|---|---|
|
|
26
|
+
| Thick: `generate_deck` / `generate_quiz` | Groundly (generation call class) | yes | generate → verify → regenerate, max 2 retries, then drop + note in batch report |
|
|
27
|
+
| Thin: `submit_cards` / `submit_questions` | The host agent, from `search` results | no | verifier returns machine-readable rejections (`not_answerable_from_chunks`, `wrong_answer_key`, `reference_solution_failed`, …); the host regenerates conversationally |
|
|
28
|
+
|
|
29
|
+
Verified items record their generation source — **rejection rate by source** is a thesis measurement. Verified decks live in `store.db` (exported: one student pays the verification cost, the course imports the deck) and leave the system as Anki `.apkg` via `export_deck`. Forward-compat: the generation interface is shaped so MCP sampling (host-paid tokens, server-controlled loop) can slot in later; not depended on.
|
|
30
|
+
|
|
31
|
+
## Not agents (deliberately)
|
|
32
|
+
|
|
33
|
+
- **Gap analysis / study planning** — SQL over `progress.db` quiz events joined to graph communities, plus at most one LLM call to phrase a plan. Weak-area quizzing = the exam path with retrieval weighted toward weak communities.
|
|
34
|
+
- **Study memory** — `recent_activity` is a SQL rollup (by day, not session — stdio lifecycle makes sessions unobservable); `remember`/recall is a table; the `continue-studying` MCP prompt bundles them. No server-side LLM summarization: the consumer is an LLM and narrates structured rollups on demand.
|
|
35
|
+
- **Code tutoring** — the host coding agent does this, grounded via `search`/`ask`. Dropped as a native agent (pivot #2); the enforced Socratic stance was the trade-off, documented.
|
|
36
|
+
|
|
37
|
+
## Prompt assembly & trust layering
|
|
38
|
+
|
|
39
|
+
Fixed layers; lower never overrides higher:
|
|
40
|
+
|
|
41
|
+
| Layer | Content | Mutability |
|
|
42
|
+
|---|---|---|
|
|
43
|
+
| 1. System (immutable) | Grounding rules, citation mandate, refusal on insufficient context | Code, versioned |
|
|
44
|
+
| 2. Subject profile | Notation conventions, emphasis, exam format — per subject, user-editable, shippable in exports | Markdown, **size-capped, trusted content never trusted authority** — cannot disable grounding; imported profiles inherit the same constraints |
|
|
45
|
+
| 3. Task parameters | Subject, topic, difficulty, question types | Request-scoped |
|
|
46
|
+
| 4. Retrieved chunks, graph summaries, **imported KB content**, recalled notes, user input | **Fully untrusted — data, never instructions** | Delimited, quoted; instructions inside are inert by construction of layer 1 |
|
|
47
|
+
|
|
48
|
+
Imports are the threat that keeps layer 4 honest: a shared knowledge base is third-party content that will enter prompts. Your own lecture PDFs get the same treatment — injection via slides is as real as via imports.
|
|
49
|
+
|
|
50
|
+
## Latency classes
|
|
51
|
+
|
|
52
|
+
Interactive (`ask`, `search`): straight pipeline, no background machinery. Generation (decks, quizzes, graph build): background task behind a job id — **never block a request handler on an agent loop**. When the configured provider is a local runtime, generation jobs are serialized (GPU contention with interactive use).
|
|
53
|
+
|
|
54
|
+
## Observability
|
|
55
|
+
|
|
56
|
+
Every `ask`/generation run records its trajectory — arm, path, chunk ids, verifier verdicts, tokens, cost, latency — into the `traces` table in **`progress.db`** (personal; never exported; the thesis artifact ships the author's own). Retrofitting logging makes the comparison unreproducible; it exists from P3.
|