feat: implement GEWU service and local agent workflows
CI / quality (push) Canceled after 0s

This commit is contained in:
vasily committed 2026-10-14 19:21:35 +08:00
1 parent 4db3f45164
commit d25c04cdd2
175 files changed
+56243 -15

No files matched your search

+182
View File
@@ -0,0 +1,182 @@
# Local setup and first use
This guide gets GEWU running on your machine so you can inspect the reader and run the current implementation checks while preparing pilot documents. The local project registry is disposable test data. It does not include pilot sources, accepted knowledge, named owners, or production acceptance policy.
## Requirements
- Python 3.12–3.14
- Node.js and npm (the web workspace has a checked-in `package-lock.json`)
- Git
- `uv` is recommended. The repository wrapper can create a virtual environment and install the Python development dependencies with `python3` and `pip` if `uv` is unavailable.
Run these commands from the repository root.
## Start a disposable local service
Set one data directory for every command in this shell. It holds the local Git knowledge repository, artifact files, identity database, and test registry. The default is `./.data/gewu` and should remain outside source control.
```bash
export GEWU_DATA_ROOT="${GEWU_DATA_ROOT:-./.data/gewu}"
mkdir -p "$GEWU_DATA_ROOT"
```
Install the synthetic project registry once:
```bash
make seed-test-registry
```
It creates `dome-performance` and `interactive-video`, plus a shared scope and test-only automatic-acceptance policies. It refuses to replace an existing registry. Only use `make seed-test-registry ARGS=--replace` if you deliberately want to reset that registry; this does not clear the rest of the data directory.
Start the API in one terminal:
```bash
make dev
```
The first run installs the Python package and development dependencies. The service listens on `http://127.0.0.1:8000`; check `http://127.0.0.1:8000/health` for `{"status":"ok","service":"gewu"}`. Leave this terminal open while using the browser or an MCP client. The local factory keeps persistent state under `GEWU_DATA_ROOT`.
## Connect the read-only browser
In a second terminal, keep the same `GEWU_DATA_ROOT` value and provision a viewer credential limited to one fixture project:
```bash
export GEWU_DATA_ROOT="${GEWU_DATA_ROOT:-./.data/gewu}"
make provision-credential ARGS="--credential-id local-viewer-dome --principal-id local-viewer --role viewer --project dome-performance"
```
The command prints the bearer credential once. Copy it into a local password manager or another secure place; do not put it in repository files, shell history, screenshots, or chat. To create access for the other fixture project, run the command again with a distinct credential ID and `--project interactive-video`.
Install and start the web workspace in another terminal:
```bash
npm --prefix web ci
npm --prefix web run dev -- --host 127.0.0.1
```
Open the local URL printed by Vite, normally `http://127.0.0.1:5173`. Paste the viewer credential into the connection form. The browser exchanges it for an HttpOnly session cookie; the bearer value is not retained in the page after connection. You can search the selected project, inspect sources and citations when knowledge exists, and disconnect to end the session.
The synthetic registry is empty, so an empty search is expected at this point. This is useful for checking service startup, credential scope, session handling, and the UI shell; it is not an end-to-end document-ingestion demo or a pilot result.
## Exercise contribution tools when you are ready
The API exposes its authenticated Streamable HTTP MCP endpoint at `http://127.0.0.1:8000/mcp`. Provision a separate credential for an agent/editor and only the project it should access:
```bash
make provision-credential ARGS="--credential-id local-agent-dome --principal-id local-agent --role agent --role editor --project dome-performance"
```
Supply the printed token to your MCP host through its protected environment or credential store as `GEWU_TOKEN`. The service URL is `http://127.0.0.1:8000/mcp`. Do not reuse the browser viewer credential. The repository's `gewu-connector` is a selected-file upload bridge, not a general MCP client; see [the local agent specification](architecture/LOCAL_AGENT.md) and [agent pack guide](../agents/gewu/README.md) for its constraints and setup. Native discovery and workflows in Claude, Codex, Antigravity, and OpenCode remain unqualified, so treat any host connection as local experimentation.
When testing contribution flows, use documents you have permission to process and preserve the exact source version and page/section locations. The fixture's automatic acceptance policy is deliberately test-only. Do not treat an accepted local record as an approved pilot decision.
## Run implementation checks
Run the Python checks from the repository root:
```bash
make test
make check
make typecheck
make boundaries
```
Run the frontend checks:
```bash
make web-check
```
Browser tests require the Playwright browser dependencies to be installed for this workspace; then run:
```bash
make browser-test
```
These checks use synthetic fixtures and local test services. They do not need your pilot corpus and do not qualify real-source extraction, semantic answer quality, deployment, or cross-platform behavior.
## Prepare the pilot materials
No real materials are needed for the local setup above. Before calling the two-project pilot qualified, the plan still needs:
- A named first administrator, named owner(s) for each project, and a named shared-library owner.
- Representative source documents for both project domains. Keep original files and identify the edition/version and the locations that support likely claims. NotebookLM exports can be supplied as supporting material, clearly identified as AI-synthesized secondary sources rather than primary evidence.
- A labeled evaluation set of 20–30 questions per project, with expected answer points and the source passages that support them. Include questions whose answer is absent or uncertain so unsupported answers can be measured.
- The intended project boundaries and rules for which records may be accepted automatically and which require owner review.
Keep the source files and question labels in a separate preparation folder until you decide what to ingest. Do not place them in the synthetic registry or commit confidential material to this repository. When ready, share the agreed corpus, question labels, and owner names so the pilot setup and evaluation can be configured against real data. The current gate status is tracked in the [implementation plan](IMPLEMENTATION_PLAN.md) and [acceptance ledger](acceptance/ledger.md).
## Reset local test state
Stop the service with Ctrl+C. To start over, stop all GEWU processes and remove only the disposable data root you configured, then repeat setup. For the default path:
```bash
rm -rf .data/gewu
```
This deletes the local registry, credentials, artifacts, workflow history, and canonical knowledge repository. Do not run it against a data root that contains material you want to keep.
## Current limitations
This is a local development service, not a team deployment. Owner-account recovery and first-owner bootstrap are not complete; no real pilot owners are configured. URL capture is disabled unless an operator configures an exact host allowlist. Search uses lexical retrieval by default; optional local embeddings require a separately installed and digest-pinned model. Consult the [operations protocol](development/OPERATIONS_PROTOCOL.md) before considering shared or remote use.
## Accounts and administration
Open `/admin` on the web service, or choose **Administration** in the navigation.
Username/password is the default human sign-in method. For first setup, choose
**Use an existing credential** and connect with your operator admin key. In
**User accounts**, create your username and chosen password with role **Administrator**.
Disconnect, then sign in with that username/password. Passwords require at least
12 characters; usernames use lowercase letters, digits, dots, hyphens and underscores.
If you do not have an operator key, provision one locally using the service's
`GEWU_DATA_ROOT`:
```bash
scripts/python-tool python scripts/provision_credential.py \
--credential-id operator-admin --principal-id operator --role admin
```
Keep the returned key in a secure credential store. Bearer secrets cannot be retrieved.
After testing your administrator account, you can revoke the old operator key from
that account's admin panel. Retaining an operator key is optional.
In the admin panel, start with **Projects → Create a project**. Enter its name,
purpose and research questions (one per line). The project ID is generated from the
name and can be adjusted before creation; the owner defaults to your signed-in ID.
The initial policy allows source registration and supported research records that
pass validation. Uncheck automatic contributions to require review instead; owner
review authentication must be configured separately. New projects do not include
other projects by default. The project appears immediately in account and agent
access selectors after creation.
Administrators create user accounts and assign their role and project access:
- **Editor**: reads assigned projects and issues contributing agent keys for them.
- **Viewer**: reads assigned projects; cannot issue contributing agent keys.
- **Administrator**: reads all projects and manages accounts and service access.
Each user opens `/agents` (**Agent credentials**) and signs in to create a key for
each agent or device. Name the agent, choose its projects, and save the displayed
secret. Configure that key as the agent host's GEWU MCP bearer credential. Each key
has a distinct principal ID, visible in the list, for attributed proposals and runs.
Users only see and revoke their own keys, and cannot grant access beyond their own
projects. Administrators can inspect and revoke all keys. Revoke confirmation names
the key; revocation invalidates bearer access immediately.
**Change your password** appears after username/password login in `/agents` or
`/admin`. Enter the current password and the new password twice. All browser sessions
for that account are invalidated; sign in again. Independent agent keys stay valid.
Disabling a user from the admin panel invalidates their sessions and all their keys.
You cannot disable your own account from its current session.
**Recent activity** in `/admin` shows the latest 50 account and credential management
actions. It excludes historical CLI actions, runtime logs and agent runs. Account and
key lists are paged. Reloads and navigation restore your existing session automatically
until it expires (eight hours after sign-in), is revoked, or you sign out. Password
changes also end the session. No secrets or CSRF tokens are persisted in browser storage.
Public password login requires HTTPS. The development proxy preserves the public
Host for the API's same-origin check. Repeated failed logins are temporarily blocked
for 15 minutes. Anonymous registration and email-based password recovery are not
included. Knowledge contributions still go through MCP.
+173
View File
@@ -0,0 +1,173 @@
# GEWU implementation plan
13 October 2026 · Planning baseline: [PRD 0.8](PRD.md), [GOAL](GOAL.md), [architecture v0.3](architecture/ARCHITECTURE.md).
Build a complete local source-to-citation workflow first, evaluate it with the two pilot projects, then expand it to every P0 requirement before full v1. The pilot serves up to five people researching Dome interactive content and an interactive video platform/service. It may use fewer clients, formats and retrieval capabilities than v1; its results must state that coverage explicitly.
This plan guides implementation; milestone status is recorded below and does not imply a pilot or release gate has passed. The repository also contains an initial agent instruction pack in the `agents/gewu` submodule. Existing pack files need integration work, not recreation. Architecture choices remain proposed until compatibility probes and the affected decisions below are resolved.
## Implementation status (14 October 2026)
M1.2/FR-P1 now has an administrator-only project lifecycle control plane. Project IDs are lowercase immutable slugs; creation supplies a named owner and matching initial supported-assessment policy, and commits `projects/<project_id>/project.md` plus `policies/<sha256(policy_id)>.yaml` in one canonical revision. Archive writes a new revision, preserves reads/history and prevents new acceptance. HTTP routes are explicitly allowlisted outside the MCP agent catalog, enforce admin/non-agent authority, browser CSRF/origin checks and a streamed 64 KiB creation-body cap, and share the canonical writer lock with acceptance. Local contract, authorization, size, persistence and race tests pass. Owner authentication and project grants exist, but named-owner account provisioning, owner reset and first-owner bootstrap remain pilot/deployment gates; protected proposal challenges are implemented separately under M1.1. See [project lifecycle evidence](acceptance/2026-10-14-project-lifecycle.md).
M1.1 now supports proposal-triggered owner review for policy-only holds. Submission binds a deterministic challenge to the proposal revision, complete before/after canonical files, affected project owners and policy versions. A separate `/owner-mcp` server exposes challenge metadata, the complete bounded diff, and one immutable authorize/reject decision; the owner token remains challenge- and audience-bound. On exact proposal resubmission, current owner grants and decisions are rechecked under the canonical writer lock, every affected domain must be covered, and the acceptance manifest records the decision digests, domains, grant versions, rationale and timestamps. Mandatory validation findings cannot be waived. Unit and MCP integration evidence is in [owner review evidence](acceptance/2026-10-14-owner-review.md). M1.1 remains partial because first-owner bootstrap, reset/recovery, OS-level owner isolation, actual named owners, and independent backup/restore qualification are still external or unimplemented.
M2.2 is in progress: GEWU pack 0.14.0 includes a copy-based installer with integrated/dedicated routing modes, isolated pack placement, reversible marked pointers for AGENTS.md, CLAUDE.md and GEMINI.md, refusal to overwrite an existing installation, and ownership-checked uninstall that preserves unrelated and later user-added files. Nine isolated filesystem tests pass, including fail-closed rejection of traversal paths, unrecognized routes in edited install state and a symlinked .agents directory. Local run checkpoints pin module hashes and reject resume when a newer verified pack snapshot changes, preserving the checkpoint for explicit revalidation. The installer deliberately leaves MCP host configuration untouched because endpoint and credential provisioning are operator-specific. Native discovery, connection, workflow verification and update/resume behavior in native clients remain NOT RUN; this partial implementation does not close M2.2.
M2.3 has authenticated `source_capture_url` and `source_capture_text` MCP operations. URL capture is gated by an exact operator-configured host allowlist; the fetch adapter rejects non-public DNS answers, pins connections to validated addresses, revalidates redirects, limits response types, bytes, duration and concurrency, and removes credentials, query strings and fragments from returned URLs. Pasted-text capture accepts UTF-8 plain text or Markdown up to 1 MB, requires a stable capture ID and source key, checks the authenticated project's submission grant, stores bytes in the private content-addressed artifact store, extracts the exact text and returns a proposal-ready source candidate with `capture_method=pasted-text`; the candidate is not registered until a typed proposal is submitted. A private disk journal binds the capture ID to the principal, project and full input digest, returns the original candidate on exact retry, conflicts on changed inputs and is bounded to 1,024 receipts. Canonical source records now distinguish URL, local-file, transcript, declared NotebookLM-export and pasted-text capture; selected VTT/SRT files retain cue timestamps and transcript provenance. URL and selected-file intake accept PDF alongside UTF-8 text/Markdown/HTML. The local connector returns a path-free source metadata candidate, derives stable file identity and content-digest revision IDs when the caller omits one, and checkpoints completed metadata so uncertain retries reproduce the same candidate; transfer state is private and bounded to 1,024 entries. Linux PDF extraction uses Poppler inside bubblewrap with network and host-user files isolated, an empty environment, read-only system mounts, and CPU, memory, time, page and output limits; tests verify page locators and inability to read a host temporary file. Mixed text and blank pages return a partial extraction; image-only/scanned PDFs return an explicit unavailable `PDF_NO_TEXT` result, while malformed, encrypted, oversized and unavailable-parser cases return stable failure codes. URL captures return proposal-ready source metadata candidates with stable sanitized-URL identity and digest-bound revision IDs; failed fetches can be registered as artifact-free `capture-failed` references. Acceptance verifies artifacts only for archived records, and unarchived records remain ineligible as factual evidence. MCP and connector fixture coverage verifies revision changes, proposal registration, authorization, resumable transfer and artifact bytes, including a local archived candidate when PDF extraction is unavailable. A canonical-registry regression test confirms that a replacement parser extraction is added under its new content-addressed ID while the previous extraction remains resolvable for historical citations (`tests/application/test_registry.py`). The local parser now accepts timestamped WebVTT and SubRip cues; proposal validation requires the cited cue times to match the extraction block, and the connector tags those files as transcripts. These synthetic cue fixtures and contracts are covered by tests. Still open: supplied NotebookLM export fixtures, parser support on Windows/macOS, real-source location verification and pilot source-path qualification.
M2.4 is in progress. Entity aliases are normalized to NFC with collapsed whitespace and checked for empty, repeated and title-duplicate values. Proposal validation compares exact entity names and aliases within the candidate's project and across only the caller-readable projects in the proposal's explicit scope. Scope is enforced both by the authenticated MCP adapter and again in the validator; evaluation does not disclose matches from unreadable or out-of-scope domains. Matches become generic `POSSIBLE_DUPLICATE_ENTITY` review findings and cannot auto-accept. Publication rechecks the credential's role and project-grant snapshot under the canonical writer lock. Aliases are indexed for lexical search. Duplicate review nominates candidates without creating accepted links or merges. Policy-only exceptions now use the protected owner review and manifest binding described under M1.1; destructive merge and reversible merge history remain unimplemented, so merge operations stay unavailable. Existing typed links bind evidence to relationship conditions and rationale. A synthetic contradiction bundle is validated and published atomically with two separately cited claims retained (`tests/domain/test_validation.py`, `tests/application/test_acceptance.py`; [contradiction bundle evidence](acceptance/2026-10-14-contradiction-bundle.md)). The service stores the proposal’s contradiction interpretation; it does not independently infer semantic conflict. Reversible merge history, complete ingest workflow coverage and shared provenance qualification remain open.
M0.1–M0.7 have a backend foundation and a first protocol-level vertical flow. Present: pinned Python and web workspaces; health path; strict v1 records and generated schemas/catalog; two-project/shared fixtures; resumable private text/Markdown intake; immutable text extraction with normalization maps; deterministic claim and relationship evidence checks; per-domain policy eligibility; private Git publication, manifest/receipt journal and crash reconciliation; and a read-only UI. A synthetic fixture now uploads through MCP, extracts a source, submits and automatically accepts an evidence-backed note, then reads the committed note and exact citation. The same transport flow submits a matching quotation at the wrong location and receives an `invalid` result with `EVIDENCE_MISMATCH`; exact accepted-proposal retry returns the original receipt without a second commit. Artifact-store contract tests verify identical bytes deduplicate while both project grants remain readable and an ungranted project remains denied. The M0.6 and M0.7 publication, recovery and replacement checks now pass, including subprocess crash boundaries, queued-work gating, SQLite generation rollback and the shared repository contract. The complete upload-to-read restart flow and authenticated human browser reading task remain open; the disposable-slice gate is not closed.
The authenticated canonical-node read is connected to the private Git revision, with project-scoped hashed credentials, revocation, rotation and a one-megabyte response cap. Streamable HTTP MCP exposes the read and contribution workflow, including non-publishing `proposal_evaluate`, author-scoped `proposal_status`, writer-locked `proposal_withdraw` and authenticated secret-free `diagnostics` over HTTP/MCP. Diagnostics binds the running catalog hash, transport- and role-authorized operations, explicit selected scope, transfer limits and canonical/index revision state; it labels connection as authenticated while leaving workflow verification separate. Agent bearer clients also have `run_create`, revision-checked/idempotent `run_checkpoint` and owner-scoped `run_status`, backed by private atomic files and the canonical writer lock. Run tests cover idempotent create, changed-input conflict, checkpoint retry and stale revisions, owner isolation, credential revocation and closed runs; the live MCP test exercises create/checkpoint/status. Evaluation tests cover valid and invalid proposals and prove evaluation does not advance canonical state or persist status. Withdrawal tests verify accepted work cannot be withdrawn, withdrawal is idempotent, a withdrawn proposal cannot later be submitted, and other agents cannot evaluate, inspect or withdraw it. Recovery tests cover status after ref-before-receipt and prepublication restart; subprocess termination after ref update and before receipt write reconstructs the original receipt after fresh service construction. An unrelated proposal is held until pending reconciliation succeeds; a killed SQLite generation rebuild retains the prior complete index and later serves the new canonical revision. The shared repository contract passes against Git and an in-memory substitute, with the canonical node reader unchanged. Full upload-to-read process restart and target-platform filesystem qualification remain open. Proposal authorship is bound to the authenticated agent; every affected project, including shared policy, requires a grant; the current credential is rechecked while holding the same lock as publication and revocation. Upload sessions, staged extractions and artifact access are principal-scoped, and artifact reads also verify project provenance. A local test-registry seed command is explicit and refuses replacement unless requested. The `gewu-connector` stdio bridge exposes only explicitly allowlisted local files, streams their bytes internally, checkpoints upload IDs privately, resumes from server-verified offsets and keeps bytes and the bearer token out of tool results. Its restart simulation uses a mock MCP service; an additional test connects it to the real local GEWU MCP endpoint. Authenticated HTTP readers can now download an immutable archived source revision only when the canonical record grants it to the requested project; responses stream verified bytes with a digest ETag, private caching, MIME sniffing protection and sandbox CSP. Native-host installation, complete process-kill qualification, public remote TLS service qualification and client workflows remain open. M1.4 now has a preliminary rebuildable SQLite FTS5 index, authenticated scoped lexical search with query/scope/index-revision-bound continuation cursors, typed-edge neighbor reads, source metadata reads and bounded node history over HTTP/MCP. Reads disclose canonical/index revisions, preserve exact citations, apply freshness warnings and budget complete responses. Search pagination retains unreturned results when response budgeting trims a page and returns a conflict when the indexed snapshot changes. Neighbor source metadata and standalone source reads require the source ingested_for grant to intersect the authorized project; node history reads validated versions from the canonical Git path. Nodes, edges, source metadata and normalized source-grant rows rebuild transactionally under SQLite schema version 4. Neighbor pagination also binds query/scope/page size/index revision, filters unauthorized endpoints in SQL before applying offsets, and expires with 409 when the indexed snapshot changes. The authenticated API returns bounded original and normalized extraction slices with source offset maps, and the web reader opens those cited slices and links the archived revision. Frontend tests cover the interaction; viewport/accessibility qualification remains open. Synthetic SQLite adapter benchmarks now report scoped warm-search p95 below 300 ms at both 10k and 100k total nodes, and index rebuild below ten minutes at 100k; real Git I/O, end-to-end service overhead, target hardware and workload, and retrieval quality remain unqualified. Language evaluation and full performance acceptance remain open. The codepoint counting profile is provisional and is not a model tokenizer. A cross-service writer-lock test now proves a concurrent publication receives `BUSY`; a comprehensive second-writer and shared-replaceLine truncated
M3.1–M3.2 have a working read-only search and citation reader. The current interface selects an authorized project, performs scoped lexical search, opens canonical notes, displays exact extracted citations, source revisions, history, typed relationship conditions and rationale, and the recorded claim assessment method/status/rationale. It keeps accepted relationships labeled separately from on-demand lexical related suggestions and exposes no knowledge mutation controls. Search includes authorized server-side node-type, past-freshness, confidence, as-of date range and exact tag/audience/use/domain filters; project, type, freshness, confidence, dates, query, facets and selected-node/revision values are reflected in the URL. Direct query/filter URLs restore after authentication, and browser back/forward restores previous searches and reruns them within the selected scope. Editing the search form creates one draft history entry, subsequent edits replace it, and submission does not create duplicate entries. Opening an item records its node ID and owning project; a shared current-node link restores current accepted state after authentication, and a revision selected from history is pinned in the URL and restored by browser back/forward. The facet groups apply before pagination, and continuation cursors bind their values. An empty query is accepted only with a knowledge-type filter, enabling a bounded “Browse problems” view while rejecting untyped browse requests. The typed browse path uses the same authorized scope, budget and cursor contract as lexical search. A paginated source browser now lists indexed records only when their provenance grants intersect the caller's selected project/shared scope, with archive, reliability, publisher, license, revision and authorized download details. Stale knowledge has a direct navigation shortcut into the URL-backed freshness filter; Problems and Topics shortcuts select the corresponding URL-backed node-type filters. Relationship panels state that excluded-project names and counts are not disclosed. Problem detail now labels accepted links as approaches and related knowledge, distinguishes the absence of visible accepted approaches from suggestions, and displays recorded tag/audience/use/domain facets. Knowledge nodes now support explicit assumption and limitation claim groups; each statement uses the same exact evidence, assessment and citation requirements as an ordinary claim, with a distinct assertion path and unique claim ID. Search, canonical reads, history and the reader carry those citations through, and the UI labels the groups separately. Revisions exposed by the bounded history response can be selected through an authorized revision-scoped read; pinned views omit current-index relationships and explain this limit. M3.3 remains partial: cross-project relationships are safely omitted rather than explained individually, and visual/accessibility acceptance is open. Frontend tests cover shared query and selected-node/revision URL restoration, search and node back/forward, and synthetic source-list, facets, problem detail, typed assumption/limitation rendering and citation paths plus distinct initial, empty-result and request-failure states. At 320×800, T3 preview evaluation of the disconnected screen confirms no horizontal document overflow; the navigation strip scrolls horizontally within its own row. T3 snapshot automation fails, so the authenticated view has no screenshot, 200% zoom, screen-reader, axe or real two-minute reading-task evidence.
M0.1 foundation verification now includes a two-test Playwright Chromium suite and a GitHub Actions workflow for push/pull-request quality gates. The suite exercises authenticated read-only UI behavior against a routed synthetic API and checks the narrow-screen citation reader; it is not live-backend or accessibility acceptance. M0.1's local acceptance criteria pass. The hosted workflow and its Python 3.12/Node 22 matrix have not yet been observed. M0.2 now exports the composed HTTP API's OpenAPI schema, includes canonical record schemas, generates TypeScript API types, and checks actual HTTP route IDs against the explicit HTTP operation allowlist; the reader uses generated request/response types. The full PRD contract audit and final budget-counting profile remain open. M0.3's two-project/shared fixture now checks that every affected project's auto-accept policy permits a source shared across project grants; a restrictive policy blocks automatic acceptance. Wrong-location, unsupported-assessment, stale-assessment, missing-policy and scope-escape cases have explicit assertions. Real pilot sources and labeled expected-answer questions remain missing. M0.4's local upload/extraction checks now explicitly reject bad chunk and artifact digests, prove interrupted data cannot be extracted, and retain byte deduplication grants and location maps; the authenticated MCP slice proves the same protocol boundary. Cross-platform and real-source format qualification remain open. M0.5 now rejects policies that attempt to waive required support assessment; tests also prove stale assessments cannot be reused, invalid submissions remain staged, and routine fixture work publishes under policy. Its local acceptance checks pass; semantic assessor quality remains a separate pilot gate.
M1.1 now has actual MCP denial coverage for viewer proposal/upload calls and a publication-time SQLite revocation test that stops a key revoked during validation before any canonical commit. Owner account provisioning, Argon2id password storage, encrypted TOTP seeds, replay protection, account-level failure throttling, explicit grants, revocation, challenge-bound five-minute sessions and the HTTPS/loopback-only authentication endpoint are implemented. Policy-only proposal holds now create exact-diff owner challenges; the isolated owner MCP can review and decide, and authorized resubmission records decision evidence in the acceptance manifest. Reset/recovery, OS-level owner isolation, first-owner bootstrap and named pilot owners remain open. No owner accounts are provisioned, so M1.1 stays partial.
### M2.1 — local GEWU pack binding (partial)
Pack version 0.14.0 now pins an MCP contract snapshot generated from `MCPServer.list_tools()`, plus the generated operation catalog and record schemas. It includes bounded authenticated pasted-text capture, transcript cue locators and source capture-method metadata. Optional `include_projects` is exposed in HTTP and MCP search scope; end-to-end tests prove omitted includes resolve project defaults, explicit empty suppresses them, authorization covers expanded scope, and direct node/source reads plus neighbor and source-list results obey scope. The pack contract snapshot is regenerated for these additive request and record fields. A contract test rebuilds a temporary service and compares discovered tool input schemas against the bundled snapshot. The pack includes a hash/snapshot verifier and local atomic checkpoint tool recording run identity, scope, lens, coverage reasons, pending operation digests, proposal revisions, receipts and output hashes; resume rejects module drift. The service now exposes private agent-owned run create/checkpoint/status operations, and the contribution protocol describes their revision/idempotency recovery contract. Proposal validation rejects node or assessment attribution that differs from the authenticated proposer. These checks cover local contract consistency and synthetic behavior only. Codex/Claude/Antigravity/OpenCode installations, real pilot workflows, native host resume and OS matrix evidence remain NOT RUN; MCP now exposes the project lens to principals with project read permission, without exposing the autonomy policy.
## Delivery boundaries
| Delivery | Included | Completion gate |
| --- | --- | --- |
| Disposable local slice | Two fixture projects plus shared; one client; text/Markdown; test policy; source upload, note proposal, exact evidence/support checks, automatic acceptance, canonical read and browser citation | One complete valid flow, an invalid-location rejection, shared-source reuse, exact retry and restart recovery. No production-data or policy claim. |
| Evaluated pilot | Selected real sources/client/format; actual roles and separate agent identities; owner-approved policy; installed GEWU pack; scoped search and problem/source reading; quality sampling | Useful cited answers with agents offline, recorded semantic quality, enforced contribution boundaries and all pilot gates passed. |
| Full v1 | Every PRD P0 feature, hybrid retrieval, required inputs, four harnesses, declared Windows/macOS/Linux coverage, offline operation, protected decisions, recovery and local-to-VPS handover | Complete P0 and non-functional evidence, independent restore, measured capacity/retrieval and native-client workflows on the target deployment. |
| Follow-up | Selected M4/M5 P1 features | Separate feature gates; these do not delay P0 scope, source retention, authority or recovery. |
Use the proposed Python/FastAPI/Pydantic service, Git canonical records, private artifacts, derived SQLite index, stdio MCP connector and React/TypeScript reading app. Resolve and lock dependencies during scaffolding. Evaluate the embedding model and vector adapter before treating their candidates as committed choices. No new stack research or package-version claims are part of this plan.
## Decisions and readiness
Record outcomes in task notes or an ADR when they change a contract, authority boundary, persistence or deployment. A pending production decision does not prevent isolated fixture work; it does prevent claiming the affected pilot/release gate passed.
| Decision | Proposed starting point / required input | Needed before |
| --- | --- | --- |
| Pilot client and platform | Use Codex on the available Linux development host for disposable tests. Owner selects the real pilot pair; Windows/Codex remains an architecture recommendation. | Native pilot acceptance |
| Pilot content | Text/Markdown for the disposable slice; collect 20 representative sources across both domains and labeled questions. Finalize project IDs; `dome-performance` and `interactive-video` are suggestions. Include the deep-research report when supplied, labeled as an AI-synthesized secondary source. | Real ingestion and quality evaluation |
| Ownership and bootstrap | Name the first admin, project owners and shared-library owner. Use separate operator bootstrap and human owner MCP authorization. | Pilot account/policy provisioning |
| Automatic acceptance | Fixture policy initially permits additive shared sources and project factual notes with valid evidence/support. Owner must enumerate production rules for sources, notes, datapoints, entities, edges and interpretations in each affected domain. Missing rules hold changes. | Pilot automatic acceptance |
| Bundle and read behavior | Adopt the acceptance-contract recommendation: atomic bundles under all affected policies, conservative base-commit conflicts, and canonical accepted-revision reads during index lag. | M0 persistence contract |
| Quality sampling | Name reviewer, sample size/cadence, semantic-error limits and correction/escalation response. Same-agent extraction/assessment is already permitted for routine notes. | Pilot evaluation |
| Retrieval profile | Evaluate local embeddings on the labeled languages/corpus; fix tokenizer, vector packaging, graph/candidate caps and index generation metadata. | M1 hybrid acceptance |
| Operating envelope | Specify concurrent users/agents, upload/archive limits, retention/rights, VPS resources, backup owner, recovery-point and recovery-time objectives, benchmark hardware and percentile. | Hosted pilot and full-v1 measurements |
| Intake and release coverage | Define the initial NotebookLM export path and supported representations, exact OS/harness pairs, and any P1 launch requirements. Start with manual supplied exports unless another path is selected. | Format/client qualification and release scope |
## Execution order
Keep the PRD's M0–M5 names. Deliver the disposable flow and pilot through a narrow pass across M0–M3, then broaden M1–M3 for v1. Each row below is a bounded work package; split it into reviewable changes around observable behaviors rather than implementing an entire layer at once.
### M0 — Contracts, fixtures and acceptance foundation
| Task | Owning module and deliverable | Depends on | Acceptance evidence |
| --- | --- | --- | --- |
| M0.1 Scaffold a runnable foundation | Bootstrap/development: Python package and web workspace, lockfiles, isolated data-root configuration, CI scripts and one health path. Follow the architecture's proposed layout; instantiate only needed modules. | None | Recorded runtime versions; backend lint/type/test and frontend lint/type/unit/browser scripts run; import-boundary checks exclude transport/provider imports from domain code. |
| M0.2 Publish shared contracts | Domain/catalog: strict versioned records, node/edge schemas, project registry/lenses, scope, proposal lifecycle, errors, upload/run limits and whole-response budgets. Generate JSON schemas, read API types and explicit HTTP/MCP allowlists. | M0.1; bundle/read decision | Valid/invalid golden fixtures; unknown fields/unsafe IDs rejected; no mutation or owner operation generated for the read API. |
| M0.3 Create acceptance fixtures | Domain/evidence: two projects plus shared, sources and expected claims/relationships, valid and adversarial locators, labeled unsupported assertions and stale dependencies. Keep illustrative PRD examples separate from executable fixtures. | M0.2 | Wrong-location quote, correct quote with unsupported assertion, stale assessment, missing policy, cross-policy bundle and scope-escape cases have explicit expected outcomes. Semantic cases evaluate assessor quality separately from deterministic checks. |
| M0.4 Implement immutable intake | Artifact/extraction stores: resumable begin/chunk/finalize, source manifests, hash dedupe without lost provenance, text/Markdown location maps, safe serialization and immutable extraction artifacts. | M0.2–M0.3 | Matching chunk retries succeed; changed chunk/incorrect hash fail; interrupted uploads are uncitable; two projects reuse one artifact; unavailable extraction remains explicit. |
| M0.5 Implement proposal validation | Validator/policy: schema, scope, links, quote-at-location, assertion-bound assessments, findings, policy-domain evaluation and revision invalidation. | M0.3–M0.4 | Mandatory checks cannot be waived by policy; changed assertions cannot reuse assessments; failing factual claims remain staged; routine fixture proposals become eligible without human approval. |
| M0.6 Implement durable publication | Repository/workflow: staged revisions, journal, exclusive writer, final authority/base/policy rechecks, private Git index, expected-head publication, committed acceptance manifest and immutable receipt reconciliation. | M0.5; identity port | One commit per accepted revision; changed-payload retry conflicts; concurrent writes serialize; unrelated files are excluded; committed-tree reads work before indexing. |
| M0.7 Prove recovery and replacement boundaries | Recovery/module contracts: inject crashes/write failures around proposal, artifact, ref, receipt and index boundaries; block new publication while reconciliation is incomplete. | M0.6 | Ref-before-receipt retry reconstructs the original receipt without another commit; live retries and unrelated queued work respect the recovery gate; a second writer is excluded. Subprocess termination immediately after ref update and before receipt write survives fresh repository/workflow adapter construction; an empty derived index rebuilds from the recovered canonical commit and returns its citations. The shared repository contract passes against Git and an independent in-memory adapter, and the node reader works against the substitute unchanged. A bad pending-manifest digest blocks an unrelated proposal before it is staged; after reconciliation is repaired, the original receipt is recovered and the queued proposal succeeds. The index transaction is killed during rebuild over an existing generation; SQLite retains that generation, then a normal search rebuilds and serves the complete current canonical set. |
M0 exits with executable contracts and a disposable accepted source/note that can be read at its committed revision. Real-source semantic evaluation and all 20-source M0 fixtures remain visible until supplied and checked; synthetic fixtures alone cannot close that PRD requirement.
### M1 — Authenticated service, MCP and retrieval
| Task | Owning module and deliverable | Depends on | Acceptance evidence |
| --- | --- | --- | --- |
| M1.1 Establish identities and authority | Identity/control: admin/editor/viewer, stable agents and hashed revocable keys, owner grants, browser sessions, restricted bootstrap and separate owner client/challenges. | M0.2; ownership decisions for pilot | Viewer proposals denied; browser admin still cannot author; rotation retains attribution; revoked key fails at publication; agent cannot impersonate assessor/owner. Protected authorization is digest-bound and expires; replay/change/grant-revocation and recovery cases pass. |
| M1.2 Expose one application core | MCP/read HTTP: catalog-backed reads, upload/proposal/status/revision/withdraw/evaluate and run operations, bounded errors/diagnostics. | M0.4–M0.7, M1.1 | Actual transports enforce capabilities and scope; no generic HTTP/CLI knowledge writes or raw queries; accepted reads disclose canonical/index revisions; diagnostics contain no secrets. |
| M1.3 Bridge selected local files | Connector: stdio MCP to service, explicit-file byte transfer, bounded upload resume, service identity checks and protocol-only stdout. | M1.2 | Selected file reaches service by bytes/hash, including a remote service; arbitrary VPS-local path interpretation fails; byte payloads and credentials stay outside model-visible responses. |
| M1.4 Deliver scoped lexical reading | Index/query: FTS, typed edges, project/shared filters and `default_includes` resolution, canonical revision reads, neighbors/history, read-time freshness and synthesis dependency warnings, complete citation groups and tokenizer accounting. | M0.7, M1.2 | IDs/redirects/graph/citations obey scope; omitted project includes resolve defaults plus shared for one project context, explicit empty includes suppress defaults, and every expanded project is authorized; stale warnings survive budgets; too-small budget returns a defined error; index deletion/rebuild preserves authority and citations; index lag is disclosed. |
| M1.5 Qualify hybrid retrieval | Embedding/vector/ranking adapters: model/native-package probes, scoped keyword/vector fusion, capped graph expansion, language fixtures and isolated index generations. | M1.4; retrieval/benchmark decisions | Top-five source recall meets the PRD target on labeled questions; old citations survive model/parser changes; offline assets work; keyword degradation is labeled. Real provider swap and generation rollback pass consumer contracts without search-consumer changes. |
M1.1–M1.4 support the pilot. M1.5 and all four native client flows are required to close full M1/v1. Authentication and enforced data isolation precede any non-disposable shared use.
### M2 — Local agent integration and input coverage
| Task | Owning module and deliverable | Depends on | Acceptance evidence |
| --- | --- | --- | --- |
| M2.1 Bind the existing GEWU pack | Agent profile/skills/pipelines: use real tool/schema contracts, pin pack/module hashes, record scope/lens, source coverage, skips, proposal IDs and receipts in durable runs. Update the separate pack submodule deliberately. | M1.2–M1.4 | Installed pack completes ingest/query, attributes same-agent assessments, reports unavailable P1 capabilities, and resumes an uncertain outcome through service status without regeneration or duplicate acceptance. |
| M2.2 Build additive installation | Harness adapters: preserve existing personas, skills and MCP entries; dedicated/integrated workspace routing; thin discovery pointers including needed GEMINI routing; copy fallback and owned-entry rollback. | M2.1, M1.3 | Install/uninstall leaves unrelated configuration intact; discovery, connection and workflow verification recorded separately; newer pack installation cannot silently alter a pinned active run. |
| M2.3 Expand source intake | Fetch/parser adapters: URL/HTML, PDF, supported local files, pasted text and supplied NotebookLM exports; transcript locators where applicable; archived downloads, source identity/revision changes, reference-only failure records. | M0.4, M1.3; format limits | Exact locations verified on real fixtures; changed URL creates a revision; failed capture preserves prior bytes; scanned/encrypted/unsupported material returns honest status. Parser replacement retains old extraction resolution. Required input paths are qualified; unsupported document subtypes are listed explicitly. |
| M2.4 Complete linking and consistency | Entity/relationship application services plus ingest skills: canonical aliases, duplicate candidates, reversible merge history, evidence/rationale-bound typed links, contradictions and supersession. | M0.5–M0.6, M2.1 | Shared dedupe preserves provenance; substantive links include conditions/support; similarity does not create accepted edges; destructive merges require authority; contradictions retain both claims. |
| M2.5 Qualify native hosts and quality | Acceptance/client fixtures: Codex, Claude, Antigravity and OpenCode on declared supported OS pairs; five common documents through two agents; sampling and labeled coverage/error evaluation. | M2.1–M2.4; quality/coverage decisions | Each supported pair transfers, rejects invalid evidence, auto-accepts eligible work, retries/resumes and retrieves citations. Convergence compares findings/support errors; no pass based on matching prose or tool listing. |
For the pilot, complete M2.1–M2.2 and the selected-format/client portions of M2.3–M2.5. Remaining matrix cells and source paths stay NOT RUN or BLOCKED until verified; they remain full-v1 obligations.
### M3 — Read-only application and pilot evaluation
| Task | Owning module and deliverable | Depends on | Acceptance evidence |
| --- | --- | --- | --- |
| M3.1 Build reading primitives | Design system/app shell: editorial tokens, typography, scope selector, result/evidence/relationship rows, freshness and system states; generated read-client types. | M0.2, M1.2; UI fixtures may start earlier | Real rendered review under the [visual protocol](development/VISUAL_DESIGN_PROTOCOL.md); keyboard navigation and error/empty/stale/index-lag states; semantic tokens replace feature-local styling. |
| M3.2 Connect search and citations | Search/node/source/history features: URL-owned scope/filters/query/selected node/revision, archived revision download/location preview, typed neighbors and citing notes. | M1.4, M3.1 | Scope → search → note → quote → exact archived revision works with agents stopped; direct query/filter URLs restore after authentication, selected node and history revision deep links and browser back/forward restore the reader; typing query/facets does not submit until Search; obsolete responses do not replace current scope; logout clears private caches; safe Markdown/preview rendering. History is bounded to the latest 20 revisions; real two-minute tasks and visual/accessibility qualification remain open. |
| M3.3 Deliver problem/topic reading | Problem/topic/staleness features: approaches, assumptions, cases, source references, facets and separately labeled related suggestions. | M2.4, M3.2 | A viewer explores multiple approaches and their conditions; excluded projects remain explicit; no capture/edit/accept/generate controls or hidden mutation client. Search supports URL-owned exact tag/audience/use/domain facets, applied in SQLite before pagination and bound into cursors. “Browse problems” lists scoped problem records without a text query, with type-bound pagination; cross-project explanations and visual/accessibility acceptance remain open. Evidence panel replacement preserves public API/navigation. |
| M3.4 Evaluate the pilot | Acceptance/quality: real two-project corpus, shared-source reuse, viewer/editor/admin and two agent identities, retry/restart, quality sampling and timed reading tasks. | Pilot portions of M0–M3; production pilot decisions | Person finds a cited answer within two minutes; location validity and assessment coverage meet PRD requirements; semantic errors and reviewer effort recorded against agreed limits. All missing full-v1 features remain listed. |
Inspect the primary path at the visual protocol's desktop/mobile sizes, 200% zoom and 320-pixel reflow. Combine automated accessibility checks with keyboard and screen-reader evidence. The pilot requires enough real UI to test research usefulness; a service-only demonstration cannot close M3.4.
### Full-v1 hardening and local-to-VPS release
This gate spans M0–M3; it is not a new product milestone. Finish all P0 coverage before labeling a release v1.
| Task | Deliverable | Required evidence |
| --- | --- | --- |
| R1 Enforce deployment boundaries | Restricted service identity, private data/credential mounts, parser sandbox/resource limits, bounded queues/uploads, authenticated artifacts, URL/DNS/redirect restrictions and MCP admission controls. | Traversal/symlink escape, malicious source instructions, secret-read, private-network fetch, unsafe preview and denied-capability cases fail through actual boundaries. Separate-process existence alone does not prove sandboxing. |
| R2 Exercise offline and portable operation | Native Windows/macOS/Linux paths, safe storage keys, non-symlink installation, local model/tokenizer/font assets and parser/vector packaging. | Existing-source validation, ingestion, index/rebuild and reading work offline; configured local-model workflow demonstrated where claimed; new external fetching reports unavailable. Declared host/OS matrix passes. |
| R3 Measure product and capacity targets | Fixed workload/corpus/hardware, latency percentiles, retrieval quality, queue saturation and cold/warm rebuild profiles. | PRD search target under 300 ms at 10,000 project nodes; 100,000-node scale and under-ten-minute rebuild evaluated with stated cache assumptions; ≥80% top-five source recall on 20–30 questions per project; acceptance rate tracked toward ≥70% after tuning. Exceptions remain visible, not redefined as passes. |
| R4 Prove backup, restore and migrations | Consistent canonical/artifact/workflow/control backups; protected owner-key recovery; schema/index migrations and rollback procedures. | Independent restore verifies hashes, grants, manifests, runs, receipts and citation reads, then disposable acceptance. Index deletion loses no authority. Revoked access is not revived; owner-key recovery and missing-key reset paths tested; recovery objectives measured. |
| R5 Transfer authority and qualify VPS | Locked release images, Compose/Caddy, private volumes, freeze/transfer/verify local state, rebuild, client endpoint switch and controlled rollback/handback. | One writer only; authenticated HTTPS/browser reading and native remote upload/accept/retry/resume/retrieval evidence; restored test copy cannot become a second authority; local and deployed revisions recorded separately. |
| R6 Close release coverage | P0 traceability and acceptance ledger, runbooks, limitations and first-month reuse follow-up. | No required gate is FAIL, BLOCKED or NOT RUN. Record shared-node reuse during the first month rather than claiming it passed on release day. |
### M4 and M5 — Selected follow-up
M4 adds P1 analysis/task briefs, synthesis compilation/refresh, deterministic evidence bundles or saved briefs, curator reports, audience lenses, matrices, comparisons, timelines and graph exploration. Decide brief semantics and release priority before implementation. Existing P0 synthesis dependency warnings and source/relationship reading are already delivered in M1/M3.
M5 adds P1 shared promotion and project export/import with redirects, provenance, policy-domain authority and durable receipts. Imports enter through MCP proposals. Exercise three projects for this later milestone; the confirmed pilot has two. P0 cross-project scope and dedupe are already enforced in M0–M2. Keep project confidentiality, automatic hooks, clustering and slide export under their existing P2 priorities.
## P0 traceability
This maps implementation ownership; the release ledger must still record each requirement separately, including the PRD's non-tabular evidence, lifecycle and source-retention rules.
| PRD requirement | Work packages |
| --- | --- |
| FR-P1, FR-P2, FR-P5 | M0.2–M0.3, M1.2, M1.4, M2.1, M3.2 |
| FR-P3 | M0.4, M2.4 |
| FR-P8 | M1.1–M1.2, M0.6–M0.7, R1/R4 |
| FR-I1, FR-I2, FR-I9 | M0.4, M1.3, M2.3 |
| FR-I3, FR-I4, FR-I7 | M0.3–M0.5, M2.1, M2.5 |
| FR-I6 | M2.4 |
| FR-I8, FR-I11 | M0.6–M0.7, M1.2, M2.1–M2.2 |
| FR-V1, FR-V2, FR-V3 | M0.5, M1.1–M1.2, M3.4 |
| FR-V4 | M2.4, M1.4, M3.2 |
| FR-V5 | M0.6–M0.7, M1.1–M1.2 |
| FR-A1, FR-A9, FR-A10 | M0.2, M1.2–M1.4, M2.2, M2.5 |
| FR-A2 | M1.5 |
| FR-A3 | M0.2, M1.4–M1.5 |
| FR-A5 | M0.6, M1.1–M1.2, R1/R5 |
| FR-A6, FR-A11 | M2.1–M2.2, M2.5 |
| FR-C3; displayed synthesis warnings (§6.3.2) | M1.4, M3.2–M3.3 |
| FR-U1, FR-U2, FR-U3, FR-U6, FR-U9 | M3.1–M3.4 |
| Non-functional requirements and success metrics | M0.1–M0.7, M2.5, M3.4, R1–R6 |
## Task completion and evidence
Each implementation task records: task ID, observable outcome, requirement IDs, owning module/public contract, dependencies, failure cases, state migration/rollback where applicable, checks and evidence. Apply the [development protocol](development/DEVELOPMENT_PROTOCOL.md) and [modularity protocol](development/MODULARITY_PROTOCOL.md); do not duplicate their contracts in every task.
The [acceptance ledger](acceptance/ledger.md) tracks each M0–M3 and R1–R6 gate, its current status, evidence scope and missing proof. Detailed fixture and command results remain in dated acceptance records. Each gate must distinguish structural pack validation, installed discovery, connection, native workflow and semantic quality; no fixture-only evidence closes a pilot or release gate.
Dependencies determine sequence, not fixed calendar dates. Staffing and source/decision availability are unknown; estimate effort after M0 contracts and the first vertical flow expose parser, client and recovery costs. Review progress at the disposable-flow, pilot-evaluation and full-v1 gates, with unresolved decisions and failed evidence visible.
## First implementation batch
1. Complete M0.1 with isolated temporary data roots, actual verification scripts and initial import-boundary checks.
2. Implement M0.2–M0.3 for a shared text source and one project factual note, plus wrong-location, stale-assessment and scope fixtures for both projects.
3. Implement M0.4–M0.7 for that bundle under an explicitly named test policy; prove exact retry and ref-before-receipt recovery.
4. Add the minimal M1 identity/MCP/connector/read path, bind `kb-ingest`/`kb-query`, and connect a minimal M3 citation view.
5. Demonstrate the disposable source-to-citation flow, then finalize real pilot inputs/policy and expand the same contracts. Do not scaffold P1 workflows before this path works.
+7 -3
View File
@@ -1,6 +1,6 @@
# GEWU architecture and engineering handbook
Started 12 October 2026; revised 13 October 2026. Architecture proposal v0.3. The initial local-agent instruction pack exists; service, connector and UI implementation has not started.
Started 12 October 2026; revised 14 October 2026. Architecture proposal v0.3. The backend, authenticated HTTP/MCP workflows, a read-only research UI, and a modular GEWU agent pack are implemented to varying levels of local verification. Consult the [implementation status](IMPLEMENTATION_PLAN.md#implementation-status-14-october-2026) and [acceptance ledger](acceptance/ledger.md) for evidence and open gates.
**Tagline:** Investigate. Connect. Remember.
@@ -8,6 +8,10 @@ GEWU (格物) draws on *géwù zhìzhī* (格物致知), a classical phrase comm
## Read in this order
For a local setup and first browser session, start with the [getting started guide](GETTING_STARTED.md). It uses a disposable synthetic registry and does not claim pilot qualification.
Start delivery planning with the [implementation plan](IMPLEMENTATION_PLAN.md): work packages, pilot/full-v1 boundaries, decision gates and PRD traceability.
1. [Reference review](reviews/ARCHITECTURE_REFERENCE_REVIEW.md): which practices to borrow, adapt or reject.
2. [Architecture](architecture/ARCHITECTURE.md): components, technology choices, alternatives and deployment.
3. [Acceptance and evidence contract](architecture/ACCEPTANCE_CONTRACT.md): records, authority, replay, crash recovery and source integrity.
@@ -34,8 +38,8 @@ Protocol language describes the intended implementation standard if this baselin
## Next implementation boundary
Start with a disposable local vertical slice: upload an explicitly selected text/Markdown source through one client, create a shared source and project note, validate exact evidence and support records, automatically accept under a test policy, retrieve the committed revision, then open its citation in a read-only browser. Exercise both pilot projects and a retry/restart failure. The test policy is not the production policy.
The disposable local vertical slice now uploads a selected source through MCP, validates and accepts an evidence-backed note under a test policy, reads the committed revision, and opens its citation in the browser. Retry, recovery and scoped-read cases have local tests. The test policy is not the production policy. Remaining work includes real pilot source and question qualification, protected owner authorization, selected native-client workflows, portability and accessibility acceptance; see the implementation plan and ledger for the next gates.
Before that boundary becomes a pilot deployment, settle the open decisions listed in the architecture. Implementing a smaller slice does not reduce the PRD's full-v1 requirements for hybrid retrieval, supported source formats, four agent harnesses and portable operation.
Runtime versions will be pinned in lockfiles during scaffolding after compatibility checks. The agent pack has an instruction/version manifest, but there are no application dependency manifests, runnable service, browser implementation or deployment tests in this repository. Skill-file validation is separate from installed discovery and live workflow acceptance.
Runtime versions are locked in the Python and web workspaces. The agent pack has a contract/version manifest, local checkpointing, and an additive installer; native-client discovery and workflow acceptance remain open. The service exposes authenticated reads and contribution workflows, and the browser reads accepted knowledge with citations. Pilot corpus evaluation, protected owner authorization, cross-platform qualification, deployment, and accessibility gates remain open. Skill-file validation is separate from installed discovery and live workflow acceptance.
+238
View File
@@ -0,0 +1,238 @@
# Foundation implementation evidence
Date: 13 October 2026
Scope: local development host, Python 3.14.7, Node 26.8.1, Linux.
Status: component checks PASS; disposable source-to-citation flow NOT RUN.
## Backend
Commands: `make check`, `make typecheck`, `./scripts/python-tool mypy src tests`, `make test`, `make schemas`, `make boundaries`, and `git diff --check`.
Observed: Ruff passed; mypy passed for application and test modules; 33 pytest tests passed; schemas and catalog regenerated; import boundaries passed; whitespace check passed. Tests cover strict contracts, fixture catalog, exact claim and edge evidence, upload resume/hash/path constraints, text extraction maps, Git expected-head publication, acceptance receipts, idempotent retries and recovery after publication-before-receipt crashes.
## Frontend and dependencies
Commands: `npm run check`, `npm run build`, and `npm audit --audit-level=moderate` from `web/`.
Observed: TypeScript, ESLint and Vitest passed (1 test); Vite production build passed; npm audit reported zero vulnerabilities.
## Limits
These checks run only on the stated local runtime. Python 3.12, other operating systems, native client discovery and workflows, MCP, retrieval, browser citations, real-source quality, deployment and restore remain NOT RUN. Synthetic fixtures do not satisfy the PRD's 20-source pilot evaluation. No pilot or release gate is claimed complete.
## Authenticated canonical read continuation
Additional commands: same backend command set plus `make check`, `make typecheck`, and `./scripts/python-tool mypy src tests`; frontend commands were rerun.
Observed: 40 backend tests passed. Added SQLite credential hash/revocation/rotation coverage and an HTTP test that confirms missing credentials get 401, malformed IDs get 422, a cross-project read gets 403, a granted read returns the committed revision and citations, and revoked credentials get 401. Local factory and SQLite identity setup reject symlinked data paths. Frontend checks/build passed; npm audit reported zero vulnerabilities. Local `make dev` now composes the Git repository and credential store under private `GEWU_DATA_ROOT` (default `.data/gewu`); `make provision-credential ARGS="..."` provisions an operator-created credential and displays it once. After the 40-test suite, the focused API/identity group was rerun and passed (8 tests); Ruff, mypy and `git diff --check` passed again.
This is one-node canonical reading, not search or the M3 browser flow. There is no human bootstrap/reset or browser session mechanism; an operator must control the local provisioning command and data root. Proposal submission and durable acceptance do not yet use the SQLite identity store.
## Authenticated MCP read continuation
The official Python MCP SDK v2.3.0 is locked as the Streamable HTTP transport. A protocol-level test connects an SDK client through the mounted MCP endpoint, lists the single `get_node` tool and reads the committed node/citations. Missing and revoked credentials return tool errors without node data. Host validation is restricted to loopback names in the local composition; public deployment host policy is not configured. The SDK's current v2 API and stdio/Streamable HTTP split are documented by the [official SDK](https://py.sdk.modelcontextprotocol.io/) and [server transport guide](https://py.sdk.modelcontextprotocol.io/run/).
The pilot fixture now has a single unambiguous shared test policy and validates JSON duplicate-key rejection.
## Authenticated contribution and source-to-citation continuation
Commands: `make check`, `./scripts/python-tool mypy src tests`, `./scripts/python-tool pytest -q`, `npm --prefix web run check`, `npm --prefix web run build`, and `npm --prefix web audit --omit=dev`.
Observed on the same local Linux/Python 3.14/Node 26 environment: 46 backend tests pass; Ruff and mypy pass; frontend TypeScript, ESLint and Vitest pass; production build succeeds; npm audit reports zero vulnerabilities. `tests/api/test_mcp_contribution.py` uses the MCP SDK client and an isolated temporary repository to upload a Markdown fixture, deny a cross-project upload, verify its hash, extract a location-mapped block, submit an attributed proposal under the test policies, confirm automatic acceptance and read the committed node with the exact citation. `tests/application/test_registry.py` seeds and parses the explicitly disposable registry. Identity revocation and publication now share the canonical-writer lock in the local composition. Catalog regenerated with all exposed contribution tool names.
This is synthetic local evidence, not a pilot result. The artifact-store contract test now uploads identical bytes for two project grants, verifies one content-addressed artifact is readable under both grants, and verifies an ungranted project is denied. Exact retry/restart across the complete source-to-acceptance flow, native host discovery, browser citation reading, retrieval/index behavior, real policy/ownership, real-source quality, other runtimes/OSes, deployment and restore remain NOT RUN. The initial UI was health-only at this point; the authenticated reader is documented later. A later MCP contribution test verifies that a quote found at the wrong locator is rejected with `EVIDENCE_MISMATCH` before a valid proposal is auto-accepted, and that exact accepted-proposal retry returns the original receipt without another commit. The disposable local-slice gate remains open until its remaining criteria pass.
## Explicit-file stdio connector continuation
The `gewu-connector` entry point exposes only `list_selected_files` and `upload_selected_file` to its local MCP peer. File IDs and paths are supplied by the operator at process launch. It rejects symlinked or non-regular files, caps bytes at the service limit, requires HTTPS for non-loopback service URLs, reads the bearer token from `GEWU_TOKEN`, and returns only file metadata, content hash and extraction IDs. A private mode-0600 state file checkpoints upload IDs and finalized artifact hashes; retries query server-verified offsets and resume without resending completed chunks, including after a connector restart.
The connector contract test simulates a restart by creating a fresh local MCP server instance against an in-process mock service. It interrupts transfer after the first chunk, interrupts again after finalization, then resumes extraction from the saved artifact. The end-to-end contribution test also invokes the connector over a real MCP Streamable HTTP session to the local GEWU ASGI service. Together they verify byte/hash equality, no source bytes or absolute paths in local tool results, rejection of an unallowlisted file ID, and rejection of a symlinked selected path. This does not prove an OS process restart/kill, public remote deployment, TLS certificate/service identity under a native host, actual client configuration, or Windows/macOS file semantics.
Updated validation: `make check`, `make boundaries`, `./scripts/python-tool mypy src tests`, `./scripts/python-tool pytest -q`, frontend check/build, `npm audit --omit=dev`, and `git diff --check` pass; the backend suite now has 60 tests. Python dependency `httpx2` is declared directly because the connector configures bearer headers on the MCP Streamable HTTP client; its v2 transport contract is documented by the [official MCP SDK client transport guide](https://py.sdk.modelcontextprotocol.io/client/transports/) and [HTTPX2 project page](https://pypi.org/project/httpx2/).
## Preliminary scoped lexical search
SQLite 3.53.4 in this Python 3.14.7 Linux runtime provides FTS5. `SQLiteSearchIndex` uses a disposable FTS5 table plus a project-indexed canonical-record table, WAL journaling and `synchronous=NORMAL`; every connection closes explicitly. Query terms are quoted and bound as a parameter, project IDs use generated placeholders, and only registered/authorized project IDs reach the query. The service reads just the small project registry for scope validation. A missing index rebuilds transactionally from a pinned Git revision; a revision change triggers a rebuild. A source/commit race returns the older index revision with an `INDEX_LAG` warning.
The tests cover HTTP/MCP search, missing/cross-project scope denial, complete citations, stale-node warnings, exact revision disclosure, budget omissions and too-small errors, FTS rebuild on a new Git revision, fresh-index reconstruction, and an injected canonical-advance/index-lag case. `EXPLAIN QUERY PLAN` on the scoped FTS query reported `SCAN node_fts VIRTUAL TABLE INDEX 0:M6`, followed by a `SEARCH indexed_nodes USING INDEX indexed_nodes_project (project_id=? AND node_id=?)`; ranking uses a temporary B-tree. This is query-shape evidence only. No 10,000-node latency or 100,000-node rebuild benchmark has run.
The current budget unit is explicitly `unicode-codepoints-v1` over the complete canonical JSON envelope. It preserves each result with its complete citations and retains warnings while dropping lower-ranked groups. This is an interim, deterministic contract and does not represent model tokens; the tokenizer/encoding decision and offline tokenizer assets remain open. Authenticated HTTP/MCP neighbor reads return typed edges with endpoint nodes, filter node endpoints by the explicit project/shared scope, preserve edge and neighbor citations, apply freshness and index-lag warnings, and use the same complete-envelope budget. Source metadata is included only when its `ingested_for` grant intersects the authorized scope. Edges, source metadata, source-grant rows and nodes are indexed in the same transactional SQLite rebuild; schema version 4 forces existing derived indexes to rebuild. Adapter tests verify source grant filtering, while HTTP/MCP tests verify project isolation, citations and transport availability. Authenticated HTTP/MCP list_projects discovery filters registry IDs against the caller's grants. Lexical search cursors bind the query, resolved project scope, shared flag, page size and SQLite index revision; invalid cross-query cursors return 422, changed-index cursors return 409, and cursors advance only past results included under the response budget. A caller can retry a budget-truncated page with a larger budget. Neighbor pagination filters inaccessible endpoints before offset/limit, binds cursors to the same index revision, returns distinct pages through HTTP, and expires old snapshots with 409. HTTP/MCP source metadata and bounded node-history reads are now tested. Source reads return 404 when the source revision is not ingested for the requested authorized project, and history returns validated versions from the canonical Git path. Archived artifact download is now available through the authenticated project source route; browser integration for exact extraction location preview, synthesis dependency warnings, CJK/language qualification, hybrid ranking and performance gates remain NOT RUN. Search/M1.4 and the broader M1 milestone remain partial.
## Authenticated reader continuation
The React reader now uses the read-only HTTP API for project discovery, scoped search, canonical note reads, source metadata and node history. It presents exact quotation text and locator details, freshness and index-lag notices, loading/empty/error states, and query/project state in the URL. The bearer credential is held in component memory, never persisted to browser storage, and the disconnect control clears the reader state. No capture, edit, approval, merge or generation action is exposed. Vite proxies `/v1` to the local API for same-origin development requests. Tests cover the connect → search → note → citation → source metadata flow and verify that localStorage remains empty; frontend type/lint/unit checks and production build pass.
The sign-in form exchanges a human viewer credential for the planned browser session; the bearer secret is dropped after exchange. Archived source bytes are now downloadable to authorized readers; the browser does not yet provide exact location preview. The T3 collaborative preview DOM measurements at 1440×900, 1024×768 and 390×844 showed no horizontal overflow; a 320×844 resize timed out. Snapshot capture repeatedly failed. Screenshots, 320 px reflow, 200% zoom, keyboard-only end-to-end review, screen-reader review and axe results remain NOT RUN. The M3 browser and visual acceptance gates remain partial.
## URL-owned search facets (2026-10-14)
Search now accepts exact tag, audience, use and domain filters through authenticated HTTP and MCP. SQLite applies each selected facet group before pagination; values within one group are ORed, while distinct groups are ANDed. Continuation cursors bind all selected facet values, so changing a filter cannot reuse an old page token. The browser initializes these filters from the URL, writes changes back to it, and clears the active cursor when a filter changes. Facet choices are informed by loaded results, while text entry permits an exact value outside those suggestions.
Tests cover matching and non-matching HTTP filters, cursor rejection after a filter changes, MCP facet forwarding, and multiple values within a facet group. Search also accepts an empty query only with a knowledge-type filter; HTTP returns 422 for an empty untyped request. SQLite tests verify problem-only results, project isolation, and stable non-overlapping cursor pages. HTTP and MCP tests verify problem browse returns the authorized fixture. The frontend test exercises “Browse problems” and confirms that it sends an empty query with `node_types: ["problem"]` and records the type in the URL. On the local Linux/Python 3.14.7/Node 26.8.1 environment, schema/catalog/MCP-contract generation and pack-manifest verification pass; Ruff, mypy (33 source files), boundary checks, all 111 backend tests, TypeScript, ESLint, all 11 frontend tests, production build and both whitespace checks pass. At 320×800, T3 DOM measurement of the disconnected screen reports document width equal to the viewport; the navigation strip scrolls horizontally. Authenticated interaction and visual snapshots remain unverified because preview snapshots fail and the available preview is disconnected. Screenshots, 200% zoom, keyboard-only and screen-reader review, and automated accessibility results remain NOT RUN. M3.3 remains partial pending cross-project explanations and the outstanding visual/accessibility protocol.
## Selected-node URL restoration (2026-10-14)
Opening a search result or related suggestion now adds `node` and `node_project` to the current scoped search URL. The node project is explicit because a visible shared record may differ from the active search project. After authentication, a direct node link performs the canonical read through the authorized project route and restores citations, history and relationships. Back navigation removes the selection and clears its private reader data; forward navigation restores it from the still-loaded result page or an authorized canonical read. Changing search or project clears the old node parameters. The route does not expose credentials or private response data.
Frontend tests cover a direct shared-node URL after connection and back/forward movement across an opened node. T3 preview could not exercise the authenticated flow: snapshots fail and the available tab remains on the disconnected screen. The production API now accepts an optional Git commit ID for node reads, confirms it appears in that node's latest 20 reachable revisions, and returns that exact node with citations. Invalid revisions receive 422; commits absent from the node history receive 404. MCP `get_node` accepts the same optional revision. The reader makes history entries selectable and stores an explicitly selected node-file commit in `revision`; it uses the latest commit that changed the node rather than the repository HEAD, which may have advanced for unrelated records. The default node URL continues to read current accepted state. Revision-pinned views omit current-index relationships and explain why. Shared URLs and browser history restore the selected revision. API tests cover the latest node-file commit differing from repository HEAD, historical content/citations, and invalid or unknown commit IDs; UI tests cover direct historical links, selection and revision back/forward. On local Linux/Python 3.14.7/Node 26.8.1, the final checks pass: 111 backend tests, 11 frontend tests, Ruff, mypy (33 source files), import boundaries, generated schemas/catalog/MCP contract, pack manifest verification, production build and root/submodule whitespace checks. T3 authenticated behavior remains unverified.
## Shared search URL restoration (2026-10-14)
After browser authentication, a direct URL containing a query and exact filters now runs that scoped search and restores its results. Browser back/forward to a different query/filter route follows the same path. Query and facet edits continue updating the shareable URL without issuing requests until the user presses Search; the first draft edit creates a history entry, later edits replace it, and submit commits without a duplicate entry. Tests verify a shared query/tag/audience URL issues one scoped request, typing remains passive, and one Back/Forward step restores and reruns the corresponding prior/next search. TypeScript, ESLint and all 13 frontend tests pass; production build and the previously recorded backend/schema/pack gates pass. Authenticated T3 preview, two-minute reading task, and visual/accessibility evidence remain open.
## Synthetic search capacity baseline (2026-10-14)
Added `make benchmark-search` for repeatable synthetic measurements through the production SQLite search adapter. On an Intel Core i7-7700HQ laptop, Linux 7.2.5, Python 3.14.7 and SQLite 3.53.4, a 10,000-node single-project corpus produced 20 scoped results; 30 warm searches measured p50 23.8 ms and nearest-rank p95 26.7 ms. Cold index rebuild plus first search was 43.6 seconds. A 100,000-node corpus split across ten projects (10,000 each) measured 10 warm searches scoped to one project at p50 132.5 ms and p95 144.4 ms; cold rebuild plus first search was 422.3 seconds. Both observed warm adapter runs are below 300 ms, and the synthetic 100k rebuild is below ten minutes.
These are partial R3 evidence, not a release pass: the benchmark feeds an in-memory canonical repository, excludes Git I/O and HTTP/auth overhead, repeats one valid claim shape, and does not test semantic retrieval quality or concurrency. The PRD workload, cache assumptions and target machine remain unfixed. Detailed reports: [10k project](search-benchmark-10000.json) and [100k total](search-benchmark-100000.json). `make check`, `make typecheck`, `make test` (111), `make boundaries`, frontend check (13), production build, and root/submodule whitespace checks pass with the benchmark script in the worktree.
## OS-level publication recovery (2026-10-14)
Added subprocess tests that call `os._exit` immediately after the canonical Git ref update and before durable receipt creation. The parent process then constructs fresh repository and acceptance-service instances, runs recovery, verifies the receipt points to the already-committed revision, checks author-scoped accepted status, and retries the proposal without advancing Git HEAD. It also starts with an empty derived index, rebuilds from that recovered canonical commit, and confirms the accepted citation is searchable. At this stage, abrupt index-rebuild termination and unrelated queued work were still open; the following evidence closes those local checks.
## Canonical repository replacement contract (2026-10-14)
Moved repository conflict and failure errors to the application-owned port and centralized its portable relative-path validation. The shared contract now runs against both the production Git adapter and an independent in-memory adapter: expected-head publication, immutable prior-revision reads, scoped file listings, introducing commit/history order, missing paths and rejection of stale writes and traversal paths. The existing `CanonicalNodeReader` is also exercised unchanged against the in-memory adapter and returns the same canonical node, revision and citation. Acceptance orchestration now catches only port-owned errors and has no Git adapter import. Ruff, mypy, import boundaries, and the full backend/frontend pipelines pass. The substitute proves dependency isolation and the contract cases listed here; it does not prove another backend's locking, durability, crash behavior or production equivalence.
## Recovery gate for unrelated work (2026-10-14)
With a proposal journal left pending after ref update, the test corrupts its expected manifest digest to force reconciliation to fail. An unrelated proposal submitted during that failure receives `RECOVERY_REQUIRED`; its proposal file is not written and canonical HEAD remains unchanged. After restoring the verified digest, explicit recovery reconstructs the first receipt, and retrying the unrelated proposal publishes successfully. This covers one unrelated queued proposal across the recovery gate; it does not claim queue-load capacity.
The index rebuild crash test now starts from an already complete eight-node generation, publishes four additional canonical nodes, and terminates a subprocess after five FTS inserts in the new generation's transaction. SQLite retains the old eight-node rows and revision with no partial writes. A subsequent ordinary search rebuilds the current 12-node generation and returns all nodes. Together with the publication and adapter-contract cases above, this satisfies the listed local M0.6 and M0.7 acceptance checks; broader PRD corpus, platform, pilot and release gates remain separate.
## Human browser session continuation
Human admin/editor/viewer credentials can exchange for an eight-hour server-side session represented by an HttpOnly, SameSite=Strict cookie. The server stores only session and CSRF digests; cookie-authenticated POST reads and sign-out require the matching CSRF header. Session creation enforces same-origin when an Origin header is present. Agent credentials are denied session creation. Browser-session principals carry a distinct auth method and cannot submit agent proposals; revoking the underlying credential makes the session unusable. The UI clears the typed bearer credential after exchange, keeps the CSRF token only in memory and signs out by revoking the server session.
Tests cover human/agent session eligibility, cookie flags, same-origin rejection, CSRF rejection and success, sign-out, session invalidation after credential revocation, and prevention of proposal submission through a browser-admin principal. This completes only the browser-session portion of M1.1. Restricted first-admin bootstrap, owner grants and the separate digest-bound protected owner authorization/challenge flow remain open pending the owner/bootstrap decision. The visual capture issues and browser reading accessibility checks above also remain open.
## Proposal status continuation
The explicit MCP catalog now includes `proposal_status`, `proposal_evaluate` and `proposal_withdraw`; the generated v1 schema includes the bounded status response record. Status returns the proposing agent's lifecycle, validation outcome/findings and durable receipt without returning the stored proposal body. Unknown proposal IDs and proposals owned by another principal both return the same unavailable result. Evaluation applies deterministic validation and authorization without writing a proposal, journal event, receipt or canonical commit. Withdrawal shares the canonical-writer lock, is idempotent, refuses accepted work, and prevents later submission of the same proposal revision. MCP tests cover valid and wrong-location evaluation, no canonical revision advance or status record before submission, author isolation, withdrawal, and denial of another agent's status/evaluation/withdrawal attempts. Recovery tests verify ref-before-receipt recovery reports accepted and prepublication recovery reports staged.
## Local GEWU pack contract and run checkpoint
Pack version 0.3.0 includes a `service-v1.json` snapshot generated from the actual MCP SDK tool inventory, including discovered input schemas, the operation catalog digest and generated v1 record-schema hashes. `test_agent_contract.py` creates a temporary service and compares its live tool schemas with the pinned pack snapshot. `manifest_tool.py verify` checks all module hashes, the module snapshot, nested schema hashes and capability names. `run_checkpoint.py` creates mode-0600 checkpoint files under a mode-0700 `Runs/` directory and atomically updates them; tests record scope/lens, source extraction references, explicit exclusion reasons, uncertain-operation digests, proposal revisions/receipts and output hashes. Resume rejects pack-hash drift, invalid output hashes, mismatched acceptance receipts and secret fields. Domain and MCP tests verify that node/assessment authorship cannot be attributed to a different agent. These are local synthetic checks: native host discovery/workflows, remote service identity, OS process-kill recovery, semantic quality, and the supported OS matrix remain NOT RUN. No project/lens read is exposed; the pack requires explicit user/workspace lens input and reports unavailable P1 capabilities. Backend lint, typing, all 69 tests, boundary checks, pack manifest verification and whitespace checks pass; frontend checks/build pass; npm audit reports zero vulnerabilities.
## Agent-owned service run continuation
The v1 MCP catalog and pack snapshot now include `run_create`, `run_checkpoint` and `run_status`. Run records are private to the authenticated agent principal, require explicit project/shared submission grants, and are stored as mode-0600 files beneath a mode-0700 run directory. Writes are atomic and serialized with identity revocation and canonical publication; creation is idempotent for the same request, while changed input under an existing run ID conflicts. Checkpoints use expected-revision compare-and-swap; identical uncertain retries return the committed revision, changed retries and stale revisions conflict, and completed/blocked runs are terminal. Tests cover create/status/checkpoint through a live MCP session, owner isolation, credential revocation, idempotent retry, changed content and stale revision rejection, and terminal state enforcement. Generated schemas/catalog and the pack contract were regenerated from the service. Local evidence only: host-side automatic run mirroring, native host resume, process-kill recovery, other operating systems and remote service identity remain NOT RUN.
## Project-authorized archived source download
The HTTP reader exposes the original archived source at `/v1/projects/{project_id}/sources/{revision_id}/artifact`. The handler first resolves and validates the canonical source revision and its `ingested_for` project grant, then checks the artifact digest, stored project provenance, media type and byte length before streaming. Responses include a digest ETag, `private, no-store`, `nosniff`, and sandbox CSP headers. The authenticated-read integration test verifies byte-for-byte output, unauthenticated denial, out-of-scope/unknown revision denial, integrity metadata and revoked-credential denial. The route is read-only and does not expose storage paths. A bounded authenticated HTTP slice endpoint returns normalized and original text with the extraction offset map after confirming both the canonical source grant and project-scoped extraction. The reader exposes an exact-location action and archived-download link; its frontend test exercises both controls and renders the captured text. Browser automation snapshot failed repeatedly, so screenshots and native browser interaction are NOT RUN. At the available 391×845 mobile viewport, DOM inspection found no horizontal overflow (document width 376 px). 320 px reflow, 200% zoom, keyboard/screen-reader review, and cross-platform behavior remain NOT RUN.
## Authenticated service diagnostics
The shared typed diagnostic contract is exposed by authenticated HTTP and MCP operations. It reports the live catalog SHA-256, service/API/schema versions, caller roles and readable projects, role-filtered operations for the current transport, optional explicit scope, source transfer size/chunk/media constraints, canonical/index revisions and index state. It reports `authenticated` connection status and `not_verified` workflow status separately. It contains no principal ID, credential identifier or token. HTTP and MCP integration tests verify catalog digest equality, authenticated-only access, project/shared-scope denial, read-versus-agent capability filtering, transfer limits and absent credential fields. The indexed-search integration additionally observes `not_built`, `current` and `lagging` states without diagnostics triggering a rebuild. The MCP inventory snapshot and generated schema/catalog were rebuilt from the actual server. Commands: `make schemas`, `make pack-manifest`, `python agents/gewu/scripts/manifest_tool.py verify`, `make check`, `make typecheck`, `./scripts/python-tool mypy src tests`, `make test`, `make boundaries`, and both root/submodule `git diff --check`. Observed on local Linux/Python 3.14.7: all 69 backend tests, Ruff, both mypy checks, boundaries and manifest verification pass; frontend checks/build and npm audit were rerun during the immediately preceding UI slice and passed (2 frontend tests, zero reported vulnerabilities). This remains local synthetic evidence; native connector/client workflows and installed skill-version verification remain NOT RUN.
### Additive pack installer
The GEWU pack was version 0.5.0 for this installer increment; the current pack is 0.6.0 and now includes a copy-based installer. In isolated temporary workspaces, six tests cover installation and removal, preservation of existing AGENTS/CLAUDE instructions and a Gemini MCP entry, preservation of unrelated skills, refusal to overwrite an occupied pack destination, rollback after a simulated copy failure, refusal to remove a modified owned routing block, and preservation of later user edits and user-added files during uninstall. The installer rejects a symlinked .agents parent and does not configure host MCP entries or store credentials. Commands: make pack-manifest, python agents/gewu/scripts/manifest_tool.py verify, make check, ./scripts/python-tool mypy src tests, and ./scripts/python-tool pytest -q tests/test_pack_installer.py; all passed on Linux/Python 3.14.7.
This is fixture evidence for filesystem behavior only. The installer has not been run in a real project workspace; installed discovery, service connection, active-run pin behavior under a native host, host MCP setup, and workflow verification remain NOT RUN. Existing pack destinations are refused, so an update cannot silently replace a pack pinned by a run.
### Allowlisted URL capture
Added the authenticated MCP operation source_capture_url. The service operator enables destinations with GEWU_FETCH_ALLOWED_HOSTS, a comma-separated exact-host allowlist; empty configuration leaves all fetches blocked. The adapter accepts only HTTP(S) on standard ports, resolves and rejects every non-global address, connects to the validated address directly, rechecks each redirect, disables compressed responses, caps responses at 50 MiB and 60 seconds, and allows two concurrent captures. The MCP handler checks the authenticated agent's project submission grant before fetching, stores UTF-8 text/Markdown/HTML through the existing verified artifact store, and strips query strings/fragments from returned source URLs. Four URL-fetch tests cover allowlisted capture and pinned address use, private DNS rejection, redirect rejection and unsupported/oversize responses. The HTML parser test and authenticated MCP integration cover visible-text extraction, active-content exclusion, normalization maps, successful HTML archive/extraction and cross-project denial. Commands: make schemas, make pack-manifest, manifest verification, Ruff, mypy, focused MCP/schema/adapter tests; all passed on Linux/Python 3.14.7.
This is synthetic fixture evidence. No public source was fetched. PDF parsing, parser process isolation, reference-only failure records, URL identity/revision updates, HTML title extraction, exact location verification against representative pages and native host workflows remain NOT RUN. HTML citation offsets point into the extracted visible text; the parser does not map them to markup byte offsets.
### HTML extraction and final local validation
The versioned parser now archives HTML while extracting visible text, removing script/style/template/noscript content and preserving normalization maps over the extracted text. HTML URL capture and extraction were exercised through the authenticated MCP fixture, including cross-project denial and archived original-byte verification. HTML citation offsets resolve against the stored visible-text extraction; they do not claim raw markup offsets. URL fetching now bounds DNS resolution to five seconds with at most two in-flight resolver tasks, in addition to the fetch duration, size and concurrency limits. The final local run regenerated schemas, catalog and pack manifest, verified pack integrity, passed Ruff, mypy (31 application and 60 source/test files), 85 backend tests, import boundaries, frontend TypeScript/ESLint/Vitest (2 tests), production build, npm audit (0 vulnerabilities), and both root/submodule diff checks. Runtime: Linux, Python 3.14.7, Node 26.8.1.
No public source was fetched. PDF parsing, isolated parser processes, reference-only failure records, URL identity/revision updates, HTML title extraction, real-page exact-location verification, native host discovery/connection/workflows, accessibility/visual qualification, real pilot corpus and owner-approved policies remain open.
## Entity consistency, search facets and reader continuation
The domain normalizes aliases to NFC and collapsed whitespace and rejects empty, duplicate, or title-repeated aliases. Proposal validation flags exact entity title/alias collisions in the candidate's project and across other projects only when both the explicit proposal scope and caller read grants permit comparison. The MCP adapter intersects those grants and scope; the validator independently enforces the explicit scope. A match produces only a generic review finding and prevents auto-accept; it does not create an entity link or merge. Publication rechecks the actor's credential, roles and project-grant snapshot. Tests cover same-domain collision, authorized cross-project and shared matches, excluded-scope/unreadable isolation, grant snapshot comparison and normal MCP contribution flow. SQLite FTS includes aliases. Reversible merge history and protected owner authorization remain unimplemented.
Search now accepts typed node-type filters and a stale-only filter in HTTP and MCP. SQL applies the filters before pagination; cursor fingerprints bind both filters. The reader exposes query, project, type and past-freshness filters in the URL, and separately labels accepted relationships and on-demand lexical suggestions. Canonical note detail exposes exact citations, source locations, recorded claim assessment details, relationship conditions/rationale and history. Frontend tests cover empty/error states, assessment rendering and the relationship/suggestion path.
The source index now supports an authenticated, paginated list_sources operation over HTTP and MCP. The SQL query joins normalized source grants before pagination, so records without a grant in the explicit requested scope are not listed. The UI's Sources navigation loads that bounded catalog and offers only project-authorized archive downloads. Integration fixtures verify list ordering/pagination, denied project scope, and MCP tool behavior; the frontend test covers catalog rendering and download-link construction.
Validation after the source-list and reader changes: schema/catalog/live MCP contract regeneration and pack manifest verification; Ruff; mypy over 33 source files; boundary checks; 102 backend tests; frontend TypeScript/ESLint/Vitest (6 tests); production web build; root and pack whitespace checks. All pass on Linux/Python 3.14.7/Node 26.8.1. T3 preview navigation works at mobile and desktop viewport settings, but snapshot automation still fails; screenshots, keyboard/screen-reader/axe review, 320 px and 200% zoom, native host workflows, real documents, measured retrieval, pilot quality, other OSes and protected owner authorization remain NOT RUN. This evidence does not close M2.4, M2.5, M3 or the release gate.
### Problem reading and recorded facets
Problem detail labels accepted links as approaches and related knowledge, explains when no accepted approaches are visible, distinguishes accepted links from lexical suggestions, and shows recorded tags, audience, use and domain metadata. Knowledge nodes now have explicit `assumptions` and `limitations` groups of ordinary evidence-backed claims. Validation enforces their assessor attribution, assertion/evidence digests and exact source locations; SQLite FTS searches their text; search, canonical reads and history return their citations; the UI renders their evidence type, status, method and rationale under separate headings. Domain tests cover eligible sourced claims and wrong-location rejection; SQLite tests prove retrieval and citation inclusion; the frontend test covers rendering. Multi-problem facet filtering, cross-project relationship explanations and visual/accessibility acceptance remain open.
At a 320×800 CSS-pixel T3 preview viewport, DOM measurement found page scroll width equal to viewport width (320 px); the rail navigation now wraps and scrolls within its own row. Snapshot automation still fails, so this is a layout measurement rather than screenshot or interactive visual acceptance.
### Evidence-backed assumptions and limitations
Added backward-compatible `KnowledgeNode.assumptions` and `.limitations` claim groups. Each entry reuses `Claim`, so it cannot be stored without typed evidence and a support assessment bound to the exact assertion and evidence digests; claim IDs must be unique across all groups, and each evidence reference must identify its group/index path. Acceptance validates source revision, extraction integrity, quote location and assessor attribution for every group; accepted node readers, history, FTS and search citations include them. Tests prove a valid claim is eligible, a wrong-location assumption is rejected, accepted publication persists the extraction and reader returns the typed claim/citation, and SQLite search retrieves the group text with its citation; the frontend test verifies separate assumption/limitation headings and content. Schemas, operation catalog, MCP snapshot and pack manifest were regenerated and verified. Full local verification passes on Linux/Python 3.14.7/Node 26.8.1: 109 backend tests, Ruff, mypy, boundaries, six frontend tests, production build and whitespace checks. This does not complete M3.3's facet navigation, cross-project explanation or visual/accessibility gates.
### Authorized cross-domain duplicate review
Proposal validation now compares entity titles and aliases across projects listed in the explicit proposal scope only when the authenticated principal can read those projects. The MCP adapter computes that intersection, and the validator independently intersects its input with proposal scope. Findings disclose only that a possible duplicate exists; they do not return the matched record. Acceptance carries the actor's role/project-grant snapshot and the identity store rechecks it immediately before publication under the canonical writer lock. Regression coverage verifies authorized project/shared matches, unreadable and out-of-scope isolation, changed authority snapshots, and the normal MCP contribution path. Validation: regenerated contracts/manifests; 106 backend tests pass; Ruff, mypy, import boundaries, six frontend tests, production build and whitespace checks pass on Linux/Python 3.14.7/Node 26.8.1. Reversible merges and protected owner decisions remain unimplemented.
### M0.7 Cross-process writer exclusion
Two separately constructed acceptance-service instances share one repository and workflow lock. The test pauses the first publisher inside its commit section, confirms the second instance receives the stable `BUSY` error, then releases the first and verifies exactly one canonical revision was published and no receipt was fabricated for the rejected writer. The test passes as part of the 106-test backend suite. This proves the local lock boundary for simultaneous writers; it does not replace process-kill recovery, filesystem-specific lock qualification or the full shared-repository adapter contract suite.
### M0.1 CI and automated browser continuation (2026-10-14)
Added `.github/workflows/ci.yml` for pushes and pull requests. It installs Python 3.12 and Node 22, syncs the locked Python and npm dependencies, verifies generated schemas/catalog/MCP contract and the GEWU pack manifest, then runs backend lint/type/boundary/tests, frontend check/build, and Chromium browser tests. `make browser-test` runs the same browser suite locally. Playwright artifacts upload when a CI job fails. The hosted workflow has not run yet, so CI execution and Python 3.12/Node 22 compatibility remain unverified.
The two Chromium tests use a routed synthetic read API and a real browser rendering the authenticated UI. One restores project, query and tag/audience facets from a shared URL, opens a result, verifies its exact citation and checks a 320 px viewport. It exposed a 40-character canonical revision expanding the page; reader metadata now wraps on narrow screens. The other confirms editing a query does not issue a search until the user submits it. Vitest discovery explicitly excludes Playwright files, keeping unit and browser runners separate. Local verification passes: 121 backend tests, 13 frontend tests, two Chromium tests, TypeScript, ESLint, Vite production build, Ruff, mypy (33 source files), boundaries, generated contracts, pack manifest and whitespace checks. The contract suite also rejects traversal-like, slash-containing and whitespace-prefixed project IDs through scope validation. These browser tests do not replace live-backend browser coverage, accessibility review, visual protocol screenshots or cross-platform acceptance.
### M0.2 Generated read API types and allowlist continuation (2026-10-14)
Added a deterministic OpenAPI exporter that composes the real local HTTP application under a temporary `GEWU_DATA_ROOT`, so schema generation cannot initialize or modify an operator's data. It adds canonical record schemas as components with rewritten local definitions; `openapi-typescript` generates `web/src/generated/api.ts`. HTTP route operation IDs now match the explicit transport operation catalog, and an integration test asserts exact set equality plus the exclusion of proposal and owner writes. The reader imports generated envelope, citation, source and request types and uses `satisfies` checks for its search, neighbor and source-list request bodies. Browser fixtures now include the required envelope and citation contract fields.
`make api-types` regenerates OpenAPI and TypeScript. CI runs it with `make schemas` and fails on generated drift. The contract audit remains partial because the PRD's full contract inventory and tokenizer/profile decision are not closed. OpenAPI generation is locally exercised against the composed app; hosted CI and the chosen codepoint/tokenizer semantics remain separate evidence gaps.
### M0.3 Cross-project policy fixture continuation (2026-10-14)
Added a deterministic source-registration fixture ingested for both pilot projects plus shared. The same proposal publishes a Dome datapoint with exact source evidence while naming both project scopes. It is eligible only when the Dome, interactive-video, and shared policies all apply; disabling source auto-registration in the video policy yields `needs-review` and prevents auto-acceptance. Together with existing wrong-location, supported-quote/unsupported-assessment, stale-assessment, missing-policy and scope-escape tests, every deterministic M0.3 example now has an explicit expected status/finding. Ruff, boundary checks and all 123 backend tests pass.
This fixture proves the cross-policy evaluator, not semantic assessor quality. The PRD's 20 hand-guided real sources, deep-research report and labeled expected-answer questions remain external inputs; synthetic cases do not close that pilot gate.
### M0.4 Upload integrity and interruption continuation (2026-10-14)
Added explicit artifact-store checks for a chunk digest that does not match its bytes, a completed upload whose whole-artifact digest differs, and an interrupted multi-chunk upload that cannot publish or expose the expected artifact. Extended the authenticated MCP source-to-citation vertical slice: premature finalize fails, `source_extract` cannot read that unfinalized artifact, a wrong chunk digest is rejected, and the same bytes subsequently upload, finalize and extract successfully. Existing coverage verifies matching chunk retry after adapter restart, text/Markdown normalization maps, immutable extraction records, shared artifact deduplication with two project grants, and explicit unavailable PDF extraction. The focused MCP flow passes. A symlink regression test confirms forged session directories and chunk symlinks are not followed; the full backend gate now has 127 passing tests. M0.4 local acceptance is complete; NotebookLM, cross-platform/parser qualification and real-source locator evaluation remain under the later pilot/input-coverage gates.
### M0.5 Mandatory policy validation continuation (2026-10-14)
Added a regression case proving `require_supported_assessment=false` is treated as a policy violation and cannot make an otherwise eligible proposal acceptable. Existing deterministic coverage verifies correct quote with unsupported assessment, exact-location mismatch, stale assertion assessment, evidence and author binding, scope escape, edge policy, and eligibility across every affected policy. The MCP source-to-citation integration verifies a failing proposal is retained as evaluated without a receipt, while its valid correction is eligible and accepted by policy. Ruff, import-boundary checks and all 126 backend tests pass. This satisfies M0.5's local acceptance checks; semantic assessor quality and complete merge workflow remain separately open.
### M1.1 Role enforcement and publication revocation continuation (2026-10-14)
The real MCP contribution test now provisions a viewer with the same project grants as an agent and confirms the viewer cannot submit proposals or begin uploads. A publication test uses the SQLite identity store and revokes the agent key between initial validation and the final publication check; submission fails with `POLICY_CHANGED`, canonical HEAD does not advance, and the proposal remains evaluated without a receipt. Ruff, mypy, import-boundary checks and all 128 backend tests pass.
M1.1 remains partial. The protected owner CLI/session/challenge profile in the architecture is proposed, not an approved live mechanism; named project/shared owners and the first-owner bootstrap authority were not supplied. No unprotected challenge endpoint or inferred owner grant is added while those authority inputs remain unresolved.
### M1.3 Remote connector service identity continuation (2026-10-14)
The remote connector HTTP client now explicitly sets certificate verification before using its operator-provisioned bearer credential. A focused factory test enters the actual remote-client context and checks that the configured endpoint is HTTPS, verification is enabled, and the credential is attached as an authorization header rather than placed in the URL or tool result. The full Python quality gate passes with 129 backend tests, Ruff, mypy (33 source files) and import-boundary checks.
This is local contract evidence only. A live remote HTTPS service, deployed certificate and native host connection are not available here, so M1.3 remains partial.
### M3.1–M3.2 Keyboard path continuation (2026-10-14)
The Chromium reader flow now focuses a search result and opens it with Enter, then verifies the exact cited evidence is visible. The search-submission flow presses Enter in the query field and confirms that no request is sent before submission and exactly one is sent afterward. Both browser tests pass. This adds keyboard activation evidence for the main search-to-citation path; it does not establish complete tab-order, zoom, screen-reader or accessibility acceptance.
### M0.7 Independent Git writer race continuation (2026-10-14)
Two separately constructed `GitCanonicalRepository` adapters start publication from the same expected head at a barrier and write distinct record paths. The compare-and-swap on the shared Git ref admits exactly one commit; both adapters observe that head, and the losing writer's path is absent from the winning tree. The test passes on the full 130-test backend suite, with Ruff, mypy and import-boundary checks. This proves the adapter-level race boundary for Git; it does not expand the shared replacement contract or filesystem/platform qualification.
### M2.2 Active-run pack-upgrade boundary continuation (2026-10-14)
Added a checkpoint test that creates a run under the current manifest, then supplies a simulated newer manifest with a changed module implementation and recomputed snapshot digest. With the new manifest treated as verified, resume fails with the pack-changed error and leaves the old checkpoint bytes intact. The full Python gate passes with 131 backend tests, Ruff, mypy (33 source files) and import-boundary checks. This verifies local checkpoint pinning; native clients still need installation/update and resume workflow qualification.
### M1.4 / FR-U2 Confidence and as-of date search (2026-10-14)
Added optional confidence values and inclusive `as_of` date bounds to the strict search request contract. SQLite applies them before pagination; the scoped cursor fingerprint includes all three values so changing a filter invalidates an existing cursor. HTTP and MCP searches exercise the filters against a fixture with distinct as-of dates, and domain validation rejects reversed ranges and repeated confidence values. The reader exposes labeled confidence checkboxes and date inputs, persists them in the URL, restores them from shared links and browser back/forward, and submits them with search. Frontend tests verify the request body and history restoration; Chromium verifies restoration from a direct URL at a narrow viewport. Generated schemas, OpenAPI, TypeScript types, service contract, and pack manifest were regenerated. Backend checks pass with 131 tests; frontend checks pass with 13 tests, build, and both Chromium tests.
This closes the previously missing FR-U2 confidence/date filter behavior for the implemented lexical reader. Native-client and pilot usability evidence remain under M2.5/M3.4.
The acceptance ledger now includes a separate status row for each of the 33 PRD P0 feature requirements, in addition to milestone and v1 release gates. It identifies FR-U2 as locally complete, retains partial/not-run statuses where implementation or real-host/pilot/deployment proof is missing, and keeps the PRD default-scope decision open under FR-P2. The matrix links each requirement to its current test evidence and remaining proof; it does not claim a P0 release pass.
+33
View File
@@ -0,0 +1,33 @@
# Minimal admin panel — 14 October 2026
Implemented `/admin` with human administrator sign-in, paged credential metadata,
project-scoped issuance, one-time secret display, confirmed revocation and latest
50 credential-management events. The activity log excludes runtime/agent logs.
Baseline: application, tests, web and schema directories were already untracked;
the agent submodule and several architecture documents were already dirty. No commit
was made and unrelated changes were preserved. The shared operation catalog and
bundled agent contract/hash were refreshed for the four new HTTP operations.
PASS:
- `scripts/python-tool pytest -q`: 179 tests.
- `npm --prefix web run check`: TypeScript, ESLint, 17 frontend tests.
- `npm --prefix web run build`: production bundle.
- Ruff check and format check, mypy, module boundary checker.
- API tests: viewer/mixed-agent denial, no authentication, CSRF/origin, body limit,
duplicate IDs, secret-free lists/events, self-revocation rejection, durable audit,
revocation invalidates bearer authentication and existing browser sessions.
- Shared preview using disposable data: sign-in, credential/project/event reads,
credential creation (201), one-time secret displayed. No operator keys modified.
- Live web `/admin` loads at `https://msi.tail0b014a.ts.net:10000/admin`; at a requested
390×844 viewport the preview reported 391×845 and no document horizontal overflow.
- Local API restarted through PM2; health succeeds and unauthenticated admin reads
return authentication errors.
LIMITED: the shared preview routed successive calls between multiple clients and
repeatedly lost the signed-in state or failed snapshot calls. Full browser revocation,
keyboard walkthrough and authenticated responsive screenshot inspection remain
unverified. Component/API tests cover creation, confirmation, CSRF and revocation;
component tests cover reconnect after session expiry. No screen-reader or axe audit
was performed. The temporary fixture server was stopped after verification.
@@ -0,0 +1,5 @@
# Contradiction bundle acceptance
A synthetic proposal carries two separate factual nodes, each with its own exact citation to an archived source extraction, and a `contradicts` edge with explicit conditions and interpretation rationale. Policy explicitly permits this edge type. The domain validator accepts the complete bundle, and the acceptance integration test publishes both nodes and the edge in one canonical commit. The test reads the committed YAML back through the strict record parser and verifies both claims and the edge are preserved (`tests/domain/test_validation.py`, `tests/application/test_acceptance.py`).
This proves deterministic validation and atomic storage of a contradiction bundle. The service does not independently determine that the facts conflict; the relationship interpretation is supplied by the proposal author and remains subject to the recorded evidence and support assessment. Real source qualification, reversible merge history, and protected owner authorization remain open.
@@ -0,0 +1,65 @@
# Hybrid retrieval dependency probe
Status: implementation and compatibility evidence. This record does not meet the
PRD's labeled top-five recall target or close FR-A2.
## Runtime
- Linux x86_64, Python 3.14.7, SQLite 3.53.4, CPU inference.
- Disposable environment: `sentence-transformers==6.1.0`, `torch==2.14.1+cpu`,
and `sqlite-vec==0.1.9`. These packages were not installed into the project
runtime.
- `sqlite-vec` extension loaded into an in-memory SQLite database and reported
`v0.1.9`; a `vec0` table accepted normalized float32 vectors and returned the
nearest row first (distance 0.00612 versus 0.88957 for the second row).
- Model: `intfloat/multilingual-e5-small`, repository revision
`614241f622f53c4eeff9890bdc4f31cfecc418b3`; local packaged tree SHA-256
`b96279dfc10e6c6c05782feead2f0155d7e16975d3ebc440cda0c46b9a038094`.
- Output was 384-dimensional and normalized to norm 1.0. Both query and passage
calls used the required `query: ` and `passage: ` prefixes.
- English query/passage cosine: 0.84662. Chinese query/passage cosine: 0.94244.
English query/Chinese passage cosine: 0.79640. This small hand-written probe is
not a relevance benchmark and makes no recall claim.
- End-to-end composition used the real local model with the Git, FTS, vector and
application search adapters. It returned `retrieval_mode=hybrid` with four
results. The vector generation and canonical index both reported revision
`734c31c64a22803134a76bba30fec25c8f322c8f`; model ID, artifact digest, content
profile and dimensions matched, and both indexes used the same SQLite file.
## Code delivered
`src/gewu/application/ports.py` defines the replaceable embedding port.
`src/gewu/adapters/embeddings.py` loads only an already-installed local model,
checks its tree digest, disables remote code and network loading, supplies E5
prefixes, and validates row count, dimensions, finite values, and normalization.
`src/gewu/adapters/sqlite_vectors.py` stores scoped vectors in immutable
generations, records revision/model/artifact/content-profile/dimension metadata,
and atomically switches the active generation using compare-and-swap. Canonical
FTS and vectors publish in the same SQLite transaction. Prior generations remain
available for rollback, and active-generation deletion is rejected.
The `retrieval` optional dependency set is pinned and included in `uv.lock`;
`sqlite-vec` is also in the dev extra so CI exercises its native adapter. Unit
tests use an injected encoder to verify model-adapter contracts without
downloading weights. Vector-index tests cover project isolation, activation,
rollback, and invalid-vector rejection (`tests/adapters/test_sqlite_vectors.py`).
The application tests cover fusion, stable pages, cursor invalidation on model
change, generation replacement, scope/filter enforcement, labeled degradation,
and bounded one-hop graph expansion. They also verify that an injected failure
after vector activation rolls back both vector and FTS publication
(`tests/application/test_hybrid_search.py`).
## Still required before hybrid acceptance
- Expand citation/scope fixtures against the PRD's labeled corpus; current
tests verify graph-origin citation propagation, filter enforcement and that
cross-project neighbors do not escape scope.
- Qualify old-citation stability across real source/parser revisions and measure
cold re-embedding and generation publication against target hardware.
- Run the PRD's labeled top-five recall set and language/corpus fixtures.
- Package model assets for offline installation and probe the native vector
runtime on Windows and macOS; qualify cold rebuild time on target hardware.
The [model card](https://huggingface.co/intfloat/multilingual-e5-small/blob/614241f622f53c4eeff9890bdc4f31cfecc418b3/README.md)
documents the candidate model. The [sqlite-vec project](https://github.com/asg017/sqlite-vec)
identifies its current pre-v1 compatibility risk; using it in the probe does not
qualify it for production storage.
@@ -0,0 +1,11 @@
# Owner review evidence
This evidence covers the local policy-exception flow implemented on 14 October 2026. It does not establish human/agent OS isolation, pilot ownership, deployment security or recovery backup acceptance.
An agent proposal held solely because `AUTO_ACCEPT_UNSPECIFIED` is not published. The service creates a deterministic owner challenge only when each affected policy domain has a named project owner with a current grant. The challenge includes proposal identity and digest, affected domains, owner assignments, current policy versions, and complete before/after canonical file contents. Its canonical JSON digest is stored with the challenge. Diffs above 512 KiB fail closed.
The owner login endpoint issues a five-minute token scoped to one challenge and service audience. The separate `/owner-mcp` server exposes only `owner_challenge_get`, `owner_diff_get` and `owner_decide`. Owner decisions require the expected proposal revision, payload digest and diff digest, a nonempty rationale, active owner account and current grant version. The store verifies the live session digest, challenge and configured audience at decision time. The decision digest and acceptance manifest bind that session ID. Identical retries from the same live session return the same result; a changed decision, session or content conflicts.
When the same proposal is submitted again, validation runs against current policy and canonical state. Authorization is accepted only when current authorized challenge records match the proposal and complete diff and collectively cover every affected domain. The acceptance test changes the policy version after approval and confirms that the old decision cannot publish. Mandatory evidence, scope, schema and support findings cannot be waived. The acceptance manifest records each challenge, owner, owner-session ID, authorization digest, domain subset, grant version, rationale and decision time. A synthetic integration test verifies the held proposal, challenge creation, decision, resubmission and manifest record (`tests/application/test_acceptance.py::test_policy_exception_requires_exact_owner_decision_in_manifest`). The owner MCP integration test exercises login, challenge metadata, exact diff and decision (`tests/api/test_owner_session.py::test_dedicated_owner_mcp_reads_diff_and_records_decision`). Adapter tests cover binding integrity, grant checks, idempotent decision retries and changed-decision conflicts (`tests/adapters/test_sqlite_identity.py::test_owner_decision_is_exact_diff_bound_and_idempotent`).
Remaining evidence includes first-owner bootstrap and named pilot accounts, password/TOTP reset and recovery, isolated OS identities, decision reconciliation under process crash and restore, real owner review usability, and deployment TLS/service identity qualification. The authorized challenge row remains until expiry; its exact proposal binding and committed manifest prevent reuse, but explicit `consumed` and `invalidated` lifecycle states are not implemented.
@@ -0,0 +1,21 @@
# Pasted-text source capture
## Observable behavior
`source_capture_text` accepts an authenticated principal, an authorized project, a stable capture ID and source key, and UTF-8 plain text or Markdown up to 1 MB. It rejects empty text, NUL bytes, malformed capture IDs, oversized metadata, unauthorized projects and requests above the byte limit. An optional original URL is normalized and stripped of credentials, query and fragment data.
The service stores the body in its private content-addressed artifact store, extracts it against the exact generated source revision, and returns a `SourceRevisionRecord` candidate marked `capture_method=pasted-text`. The operation does not register the source; the agent submits the returned candidate through the normal typed proposal workflow.
Capture metadata is checkpointed in a private disk journal keyed by authenticated principal and capture ID. The journal binds the project and a digest of all capture inputs, stores no source body, returns the original candidate on exact retry, and rejects reuse with changed inputs or a different project. The journal retains at most 1,024 receipts. Source records also identify `url-fetch` and `local-file` capture methods; records created before this field existed load as `unspecified`.
## Verification
- `tests/api/test_mcp_contribution.py` exercises the live Streamable HTTP MCP path, including editor success, viewer and cross-project denial, exact retry, changed-input conflict, URL credential redaction, body digest, stored extraction and citation text, invalid metadata/control characters and the 1 MB limit.
- `tests/application/test_uploads.py` recreates the artifact-store adapter and verifies receipt recovery, principal isolation and conflict behavior across restart.
- `tests/api/test_stdio_connector.py` confirms local-file candidates identify their capture method; the URL fixture confirms `url-fetch` provenance.
- Generated JSON schemas, catalog, HTTP OpenAPI, TypeScript types and the GEWU 0.10.0 MCP contract snapshot regenerate and verify.
- Full local verification: 156 backend tests, Ruff, mypy (36 source files), import boundaries, 13 frontend tests, production build and both Chromium tests pass.
## Remaining qualification
This closes a synthetic local pasted-text path only. Supplied NotebookLM exports, native-host workflows, Windows/macOS parser support, representative real sources, and real-source citation accuracy remain open under M2.3 and M3.4. The receipt journal is bounded; retries after receipt eviction can create a fresh candidate.
@@ -0,0 +1,26 @@
# Project creation in administration — 14 October 2026
The administrator UI now includes a Projects section, existing project summaries,
and a creation form using the established `/v1/admin/projects` API. It collects a
name, stable project slug, owner ID, purpose and 1–30 research questions. Owner
identity defaults to `/v1/me`. Creation refreshes project options for account and
credential grants without reloading the page. Failures preserve the form for retry.
The default initial policy explicitly permits source registration and supported
research record types that pass service validation. The checkbox explains this and
can require review instead. Protected intent/policy/deletion/merge changes retain
owner authorization. Cross-project includes start empty. No project is created on
the operator's behalf; the operator fills in the form and submits it.
PASS: TypeScript, ESLint, 20 frontend tests and production build; existing project
administration API test; deployed admin page HTTP 200. The new integrated UI test
covers identity defaults, slug generation, policy and CSRF payload, server conflict
preserving inputs, successful creation, and updated account/key grant selectors.
LIMITED: shared preview status/open calls timed out. Rendered screenshot, keyboard
and responsive browser checks could not be completed during this change. Existing
styles and semantic form controls are reused; no accessibility audit is claimed.
The working tree already contained uncommitted application work. Changes were kept
in the admin UI, tests, CSS and setup documentation; no commit or knowledge mutation
was performed.
@@ -0,0 +1,50 @@
# Project registry lifecycle evidence
Status: local FR-P1 implementation acceptance. This does not establish protected
owner authorization, a named production owner, native-client behavior, or pilot
acceptance.
## Contract
- Project IDs are lowercase hyphen-separated slugs and are immutable.
- The canonical entry is `projects/<project_id>/project.md` with strict
`ProjectRecord` YAML frontmatter. Its matching initial `AutoAcceptPolicy` is
committed alongside it at `policies/<sha256(policy_id)>.yaml`.
- Project creation requires a named owner, active status, a matching policy,
supported-assessment enforcement, and default includes that resolve to a
registered project or shared. Project and policy publish in one expected-head
commit.
- Only an authenticated non-agent administrator can access the HTTP control
routes. Browser-session writes require same-origin and CSRF checks. The streamed
create body is capped at 64 KiB. These control-plane operations do not appear in
the MCP agent catalog and do not bypass proposal validation.
- Archive is idempotent and one-way through this API. It writes a new canonical
project revision, retains prior records/citations, and makes the project
read-only. Paused and archived projects stay readable but cannot accept new
changes. Shared cannot be created or archived as a project.
- Lifecycle writes use the same authority lock as proposal publication, so an
archive cannot race an acceptance decision.
## Evidence
`tests/api/test_project_admin.py` verifies unauthenticated and viewer denial,
denial when an identity combines `admin` and `agent`, authorized create/list/
archive, duplicate conflict, missing CSRF, wrong Origin, browser-session success,
and a 413 response above the body limit. `tests/application/test_registry.py`
verifies the project frontmatter and policy are read into validation context,
archive advances canonical revision and remains idempotent, the legacy JSON project
entry is promoted by canonical archive, and the shared writer lock excludes an
archive while held. `tests/domain/test_validation.py` verifies
paused and archived projects cannot auto-accept a proposal. Contract tests cover
the paused enum and slug IDs. The generated schema, OpenAPI, TypeScript contract,
agent contract snapshot and GEWU pack 0.7.0 manifest are regenerated and verified.
Latest full local run: 153 backend tests, Ruff, mypy over 36 source files,
boundaries, 13 frontend tests, production web build, two Chromium flows, schema
and API-type generation, pack manifest verification, and both workspace
whitespace checks passed on Linux/Python 3.14.7/Node 26.8.1.
The `owners` field is recorded as project metadata; this flow does not verify the
owner's identity or implement owner challenges/grants. First-owner bootstrap,
owner-only project intent/policy changes, Windows/macOS behavior and live remote
deployment remain open.
@@ -0,0 +1,30 @@
# Restore sign-in after page reload — 14 October 2026
The page now restores a valid human session on mount through `GET /v1/session`,
using the existing HttpOnly cookie. It recovers an in-memory CSRF token and reloads
permissions and data. Reloading or navigating between library, administration and
agent credentials no longer requires passwords while the session remains valid.
A stable one-way CSRF token is derived from the private session secret. An additive
`restored_csrf_digest` column preserves the original token for other tabs and already
issued sessions. Restoration neither exposes the cookie nor extends its eight-hour
expiry. Same-origin checks and a custom client header protect restoration. Expired,
revoked and signed-out sessions return 401; the UI then shows sign-in. No local or
session storage is used. A failed restored admin-page permission check preserves the
valid session rather than signing the user out of other surfaces.
PASS: 183 backend tests; 22 frontend tests, TypeScript, ESLint and production build;
Ruff check/format, mypy, module boundaries and generated operation/agent contracts.
Regression cases include pre-upgrade migration, old-tab CSRF preservation, stable
restoration, original expiry, revocation, origin/header checks, remount restoration
in admin and library, and explicit sign-out returning to the login form.
Live HTTPS smoke check: session restoration 200 twice, stable CSRF, unchanged
expiry, authenticated admin project list 200, sign-out with the original tab's CSRF
200, restoration after sign-out 401. The smoke check's temporary session was revoked;
no operator account password or existing user session was changed.
LIMITED: collaborative preview navigation timed out, so a complete rendered browser
reload walkthrough was not observed. Remount behavior is covered by component tests
and the deployed HTTPS session protocol was verified directly. No knowledge records
were changed, unrelated work was preserved, and no commit was made.
@@ -0,0 +1,7 @@
# Timestamped transcript locator acceptance
The local extractor now accepts WebVTT (`.vtt`) and SubRip (`.srt`) inputs and emits timestamped cue blocks while preserving the original cue text and character-offset mapping. Transcript locators carry the cue's start and end milliseconds in addition to the quote span. Proposal validation rejects a locator when its cue timing does not exactly match the cited extraction block. The selected-file connector infers transcript provenance for these formats; an explicit provenance label is included in its retry identity.
The evidence citation view displays transcript cue timing; a frontend reader test asserts the rendered range for a transcript citation (`web/src/shell/App.test.tsx`). Unit tests cover VTT and SRT timestamp parsing, exact offsets, malformed and reversed cues, proposal acceptance for a matching cue, rejection for a shifted cue, connector media types, and transcript provenance (`tests/adapters/test_text_extractor.py`, `tests/domain/test_validation.py`, `tests/api/test_stdio_connector.py`). Generated JSON schemas, catalog, OpenAPI and TypeScript types were refreshed. Pack contract snapshot and hashes are refreshed with GEWU 0.10.0.
This verifies synthetic WebVTT/SubRip fixtures and the local implementation. Supplied NotebookLM export examples, real-world transcript fixtures and timestamp accuracy in the pilot source path remain open; the declared NotebookLM provenance option does not authenticate or qualify an export. Windows/macOS support and native-host workflows also remain unverified.
@@ -0,0 +1,35 @@
# Password accounts and personal agent keys — 14 October 2026
Implemented username/password login in the library and admin surfaces, administrator
account creation/disable, self-service password changes and `/agents` for personal
agent keys. The development proxy preserves the public Host to fix the reported
same-origin login failure. Existing bearer credentials remain usable for setup.
An initial administrator account was created at the owner's request; no password or
bearer token is recorded in this evidence document.
PASS:
- Full backend suite: 181 tests.
- Web check: TypeScript, ESLint and 19 component tests.
- Production web build; Ruff check/format, mypy, boundary and agent manifest checks.
- Account API scenarios: hashed passwords, generic input errors without secrets,
HTTPS/origin/CSRF/body limits, login throttling, password change invalidates all
sessions, wrong-password rejection, agent identity isolation, owner-only key
listing/revocation, grant escalation denial, read-only user limitations, account
disable cascades to agent revocation, self-disable rejection and durable accounts.
- Added targeted coverage for owned-key rotation and legacy account-key revocation
cascading to the user's agent keys.
- Live HTTPS smoke check: password login 200, Secure session cookie, authorized user
list 200, CSRF-protected sign-out 200. The test session was revoked afterward.
- Public-origin requests now pass through the development proxy; attacker-origin
requests still fail with the same-origin error.
LIMITED: the shared preview switched between clients, stale pages and renderer
errors. The fixture page loaded, but the full visual/keyboard/password walkthrough
could not be completed reliably. The component and API tests cover the behavior;
no screen-reader or axe pass is claimed. Temporary fixture HTTPS forwarding and
server processes were removed. Native agent-host setup remains outside this slice.
Existing dirty/untracked application state was preserved, no commit was made, and
no knowledge records were changed. Account migration adds tables and a nullable
credential owner column; no existing bearer secret is rotated during migration.
+90
View File
@@ -0,0 +1,90 @@
# GEWU acceptance ledger
This ledger records the implementation-plan gates against evidence currently present in the worktree. A local fixture pass does not establish pilot, native-host, deployment, or release acceptance. “Complete” means the named gate's implementation-plan acceptance checks have recorded evidence; broader pilot and release requirements remain separate. “Partial” means only part of the named gate has qualifying evidence. “Not run” means no qualifying evidence has been recorded. Reassess affected rows whenever scope or evidence changes.
## Evidence context
- Source plan: [implementation plan](../IMPLEMENTATION_PLAN.md); requirements: [PRD](../PRD.md).
- Runtime for the latest full local verification: Linux, Python 3.14.7, Node 26.8.1, npm 11.19.0, Chromium (Playwright).
- Workspace base revision: `4db3f451643130fae0e003d079c05279483ce123`; implementation and evidence changes are uncommitted in the shared worktree.
- Latest commands: `make test && make check && make typecheck && make boundaries`, `npm --prefix web run check && npm --prefix web run build`, `make browser-test`, `make api-types`, `python agents/gewu/scripts/manifest_tool.py refresh && python agents/gewu/scripts/manifest_tool.py verify`, `git diff --check`, and `git -C agents/gewu diff --check`.
- Latest observed results: schemas, OpenAPI and TypeScript API types regenerate cleanly; pack 0.14.0 manifest verifies; Ruff, mypy (38 source files), boundaries, all 178 backend tests, both Chromium browser tests, including keyboard search/result activation at 320 px, TypeScript, ESLint, all 14 frontend tests, production build and whitespace checks pass. Transcript locators are asserted by a reader UI test and project-lens reads are scoped, exclude policy content and are covered over MCP. See the [transcript acceptance note](2026-10-14-transcript-locators.md). HTTP/MCP default and explicit project includes, expanded-scope authorization and scoped direct/citation/neighbor/source-list reads are covered. Canonical-registry tests confirm new parser extractions do not remove the prior content-addressed extraction used by historical citations. Authenticated pasted-text capture checks authorization, the 1 MB bound, exact retry/idempotency, receipt survival across adapter restart, artifact/extraction integrity, credential redaction and capture provenance. Search includes type, freshness, confidence and as-of-date filters; confidence/date values persist in direct URLs and filter changes expire old cursors. Scoped problem browsing and selected-node/revision restoration through browser back/forward are covered. Two independent Git repository adapters racing from one head produce exactly one published tree, with no losing-writer file. Active run checkpoints refuse resume under a changed verified pack snapshot. The connector's remote HTTP client explicitly verifies TLS certificates before sending its bearer credential. Synthetic SQLite measurements are recorded for 10k and 100k nodes. See [foundation evidence](2026-10-13-foundation.md) and the [benchmark reports](search-benchmark-10000.json), [100k scale report](search-benchmark-100000.json) for scope and limits.
## Milestone gates
| Gate | Status | Evidence and remaining proof |
| --- | --- | --- |
| M0.1 Foundation | COMPLETE | The plan's local foundation checks pass: recorded runtimes, 175 backend tests (including contradiction-bundle publication, sqlite-vec generation, atomic hybrid-index rollback, project-registry lifecycle tests, HTTP/MCP scope resolution, retained historical extractions across parser replacement and pasted-capture retry recovery), 14 frontend tests, lint/type checks, generated-contract and pack verification, and import-boundary checks. A GitHub Actions workflow repeats the locked Python/web checks, generated-contract and pack verification, browser installation and Chromium suite; `make browser-test` exposes the suite locally. Both Chromium tests pass, including URL-restored scoped search/citation reading at 320 px and passive query submission. The hosted workflow has not yet run; Python 3.12/Node 22 and cross-platform qualification remain open. |
| M0.2 Contracts | PARTIAL | Strict v1 models, generated record schemas/catalog, generated OpenAPI plus TypeScript read API types, and MCP snapshot checks pass. A new OpenAPI contract test asserts HTTP route operation IDs equal the explicit HTTP allowlist and exclude proposal/owner writes; browser request bodies and response records now use generated types. Unknown fields and unsafe IDs are rejected. A current PRD-to-ledger cross-check finds all 33 P0 requirement IDs tracked exactly once; the payload-level audit of each public contract against the full PRD, plus the production tokenizer/counting profile decision, remains open. |
| M0.3 Fixtures | PARTIAL | Two project/shared fixtures and wrong-location, unsupported-assessment, stale-assessment, missing-policy and scope-escape cases have explicit expected outcomes. A cross-project source bundle now proves all affected project/shared policies must permit acceptance; removing automatic registration from one project's policy changes the result to `needs-review`. Tests exercise deterministic policy handling separately from support labels; they do not score semantic assessor quality. The PRD's 20 representative real sources and labeled pilot questions are still missing. Synthetic transcript fixtures separately verify VTT/SRT cue parsing and exact cue-locator validation; see [transcript locator evidence](2026-10-14-transcript-locators.md). See `test_validation.py` and `proposal_fixtures.py`. |
| M0.4 Immutable intake | COMPLETE | Acceptance evidence covers matching retries and restart, changed chunk and incorrect digest rejection, interrupted uploads that cannot finalize or be extracted, forged session/chunk symlinks that are not followed, immutable extraction storage, text/Markdown source-location maps, byte deduplication with both project grants preserved, and explicit unavailable PDF extraction. The authenticated MCP vertical slice exercises interrupted and valid upload/extract behavior. NotebookLM exports, OS/parser qualification, and real-source locator verification remain external pilot/input-coverage work tracked under M2.3 and M3.4. |
| M0.5 Validation | COMPLETE | Exact quote-at-location, stale assessment, attribution, edge binding, project/shared policy, scope and mandatory support checks are executable. The validator rejects a policy that tries to disable required support review; invalid proposals remain staged without receipts, and routine fixture proposals are eligible and publish through policy without human approval. Evidence: `test_validation.py`, `test_mcp_contribution.py`, `test_acceptance.py`. Real assessor quality belongs to M0.3/M3.4; the broader merge/consistency workflow remains under M2.4. |
| M0.6 Durable publication | COMPLETE | Plan acceptance checks pass: exact retries return one immutable receipt/commit; changed payload conflicts; concurrent writers are excluded; only explicit records are committed; and reads work while the derived index is unbuilt. Evidence is in `test_acceptance.py`, `test_git_repository.py`, and `test_search_api.py`; crash recovery details remain tracked by M0.7. |
| M0.7 Recovery and replacement | COMPLETE | Injected failures before commit, after Git ref update, and before receipt are covered; subprocess termination at the latter ref/receipt boundaries recovers the same receipt without another commit. A killed SQLite rebuild rolls back to the last complete generation, and a normal search rebuilds from current canonical state. A bad pending-manifest digest blocks an unrelated proposal before staging; after repair, recovery writes the original receipt and the proposal publishes. Service-level concurrent writers are excluded, and two independent Git adapters racing from the same expected head prove exactly one ref update succeeds with no losing-writer file in the committed tree. The shared repository contract passes against Git and an in-memory substitute, and `CanonicalNodeReader` works unchanged with the substitute. See `test_acceptance.py`, `test_git_repository.py`, `test_sqlite_search.py`, and `test_canonical_repository_contract.py`. Broader shared replacement qualification remains open. |
| M1.1 Identity and authority | PARTIAL | Viewer credentials are denied actual MCP proposal/upload operations; browser-admin principals cannot author; rotation preserves stable agent grants; and revocation during validation is rechecked before publication. Owner provisioning/auth foundations use Argon2id, encrypted TOTP seeds, replay protection, five-failure throttling, explicit grant-versioned challenge/session bindings, and revocation. The `/auth/owner-session` endpoint requires HTTPS (loopback HTTP for development), a 4 KiB body cap and no-store responses. Policy-only holds create exact before/after diff challenges from named project owners; a separate `/owner-mcp` surface authenticates challenge-bound sessions, exposes the complete digest-checked diff, and records idempotent immutable decisions. A resubmission publishes only when current decisions cover every affected domain; the acceptance manifest records owner, challenge, decision digest, rationale, domains and grant version. Tests cover auth separation, owner-MCP operations, decision replay/change, policy-exception acceptance and manifest evidence (`test_owner_session.py`, `test_sqlite_identity.py`, `test_acceptance.py`). First-owner bootstrap, reset/recovery, actual owner OS isolation, crash-qualified decision reconciliation, named pilot owners and restore/key recovery remain open; no accounts are configured. See [owner review evidence](2026-10-14-owner-review.md). |
| M1.2 Application transports | PARTIAL | Authenticated HTTP/MCP allowlists, reads, contributions, status, diagnostics and runs have integration tests. Admin-only project registry list/create/archive control operations are separately allowlisted on HTTP and protected by bearer/session authorization, CSRF, request-size limits and canonical writer serialization. Remote TLS/deployment qualification remains. |
| M1.3 Local connector | PARTIAL | Explicit-file byte transfer, bounded resume and local MCP integration are tested. Remote endpoint URLs require HTTPS (loopback HTTP only for development), and the connector explicitly enables certificate verification before attaching the bearer credential; a factory contract test covers these settings. A live remote TLS service identity check and native host workflows remain unverified. |
| M1.4 Scoped lexical retrieval | PARTIAL | SQLite FTS, scoped search, pagination, type/facet/confidence/as-of-date filters, neighbors, history, citations, index status, and project-default resolution are tested. HTTP and MCP integration tests prove omitted includes expand a single project context to `default_includes` plus shared, explicit empty includes suppress defaults, every expanded project must be authorized (including explicitly requested neighbors), and direct node/source reads, citations, neighbors and source lists obey scope (`tests/api/test_scope_resolution.py`). Synthetic adapter runs report 10k-project warm-search p95 26.7 ms and 100k-total warm-search p95 144.4 ms; these do not include Git I/O or HTTP/auth, so end-to-end performance and target-hardware qualification remain. Hybrid retrieval and tokenizer qualification remain. |
| M1.5 Hybrid retrieval | PARTIAL | Configured local mode publishes FTS, canonical nodes and scope-partitioned vector generations in one SQLite transaction. Search fuses a stable top-100 vector candidate head with lexical ranks using RRF, then expands at most 10 seeds across at most 50 one-hop typed edges; expanded nodes retain their origin and edge in the response and citation set. All vector and graph candidates are rechecked against scope and active search filters. Cursors bind to the model/content profile, and keyword fallback is labeled without issuing a continuation cursor. Tests cover project isolation, filters, stable pages, generation replacement/retention, failed-build rollback and graph expansion. A disposable Python 3.14 CPU run of the real pinned E5 model returned `retrieval_mode=hybrid` with vector and canonical revisions equal. The candidate pair probe scored 0.84662 English and 0.94244 Chinese cosine, but this is not a relevance benchmark. Labeled top-five recall, offline redistribution, and cross-platform packaging remain open (`docs/acceptance/2026-10-14-hybrid-probe.md`). |
| M2.1 GEWU pack | PARTIAL | Pack 0.14.0 contract snapshot, generated schemas/catalog, checkpoint and manifest verification pass. MCP project-context reads return only lens fields and enforce project read grants. Real host installation and native resume are unverified. |
| M2.2 Additive installer | PARTIAL | Nine isolated installer tests pass, including fail-closed checks for traversal paths, unrecognized route names in edited state and a symlinked .agents directory. Local run checkpoints pin module hashes and reject resume when a newer verified pack snapshot changes; the existing checkpoint is preserved. Host MCP configuration, discovery, connection and active-run update behavior in native clients remain unverified. |
| M2.3 Input coverage | PARTIAL | URL, selected-file and bounded authenticated pasted-text capture paths plus Linux PDF sandbox fixtures exist. WebVTT/SubRip parsing preserves cue timestamps and quote offsets; validation requires transcript locators to match the cited cue, connector candidates are marked `transcript`, and the reader renders exact cue timestamps. Tests cover cue parsing, malformed/reversed timestamps, exact/mismatched evidence timing, media types, source provenance and rendered cue-time labels (`tests/adapters/test_text_extractor.py`, `tests/domain/test_validation.py`, `tests/api/test_stdio_connector.py`). Pasted text is UTF-8 plain text/Markdown up to 1 MB; integration coverage verifies project authorization, artifact digest, exact extracted bytes, source capture-method provenance, credential redaction and rejection of oversized or invalid input (`tests/api/test_mcp_contribution.py`). A private bounded receipt journal returns the same candidate after an exact retry, survives adapter restart, and conflicts on changed input or project scope (`tests/application/test_uploads.py`, `tests/api/test_mcp_contribution.py`). A regression test verifies that a replacement parser extraction receives a new content-addressed ID while the prior canonical extraction remains resolvable for a cited node (`tests/application/test_registry.py`). See [pasted-text capture evidence](2026-10-14-pasted-text-capture.md). Windows/macOS, supplied NotebookLM exports, representative real sources and real-source location verification remain. |
| M2.4 Linking and consistency | PARTIAL | Alias normalization, scope-authorized duplicate review, typed links and contradiction preservation are tested. A synthetic two-claim contradiction bundle passes validation and commits both separately cited nodes plus the typed relationship in one commit, with committed records read back intact (`tests/domain/test_validation.py`, `tests/application/test_acceptance.py`; [evidence](2026-10-14-contradiction-bundle.md)). Policy-only exceptions now have a protected owner workflow; reversible merge history and merge operations remain unimplemented. This is storage/contract evidence, not semantic conflict evaluation. Complete provenance qualification remains open. |
| M2.5 Native hosts and quality | NOT RUN | No qualified Codex/Claude/Antigravity/OpenCode and OS matrix; no two-agent common-document convergence or semantic sampling. |
| M3.1 Reading primitives | PARTIAL | Reader states, scope controls, keyboard activation of a search result and Enter-to-submit are exercised in Chromium; transcript citation labels have a frontend rendering assertion; a 320 px no-overflow DOM measurement exists. Feature colors now resolve through semantic surface, text, border, accent and status tokens in `web/src/styles/base.css`; the token-only stylesheet passes the UI suite, production build and both Chromium flows. Calculated foreground/background contrast for primary, secondary, muted, navigation, warning, link and error text ranges from 4.74:1 to 13.41:1. T3 preview status reports a 320 px attached page, but snapshot automation failed on two retries, so rendered screenshots, 200% zoom, complete keyboard traversal and screen-reader/axe review remain open. |
| M3.2 Search and citations | PARTIAL | Synthetic scope-to-search-to-note-to-citation/source path, direct shared query/filter URL restoration after authentication, including confidence and as-of date range, prior-search and shared selected-node/revision restoration through browser back/forward, historical citation reads and stale/error states are tested. Chromium now activates a result and submits search by keyboard; transcript citations render exact cue timestamps in the evidence location label. Query and facet typing remains passive until Search. History is limited to 20 revisions; a real two-minute task, visual/accessibility review, and stale/index-lag end-user evidence remain missing. |
| M3.3 Problem/topic reading | PARTIAL | Problem detail, accepted links versus suggestions, conditions, recorded facets, evidence-backed assumption/limitation claims and missing-approach state exist. Exact tag/audience/use/domain filters and a scoped, paginated problem browse are URL-owned and server-side; cross-project explanations and visual/accessibility acceptance remain. |
| M3.4 Pilot evaluation | NOT RUN | No real corpus, owner-approved policies, user reading task, semantic quality sample or reviewer-effort record. |
## Full-v1 release gates
| Gate | Status | Evidence and remaining proof |
| --- | --- | --- |
| R1 Deployment boundaries | PARTIAL | Unit/integration tests exercise sandboxed PDF extraction, URL/DNS restrictions, scope and artifact boundaries; actual deployed-service adversarial qualification remains. |
| R2 Offline and portable operation | NOT RUN | Linux development fixtures only; Windows/macOS, offline packaging and native-model workflows are unqualified. |
| R3 Product and capacity targets | PARTIAL | Synthetic adapter benchmark evidence exists at 10k nodes (30 warm queries: p50 23.8 ms, p95 26.7 ms; cold rebuild plus first search 43.6 s) and 100k nodes across ten 10k-node projects (10 warm queries scoped to one project: p50 132.5 ms, p95 144.4 ms; cold rebuild plus first search 422.3 s). Reports use this Linux i7-7700HQ/8-logical-CPU machine but an in-memory canonical repository and repeat synthetic claim shape. They omit Git disk reads, HTTP/auth, contention and real relevance; target hardware/workload decisions, queue saturation, and the 20–30-question-per-project top-five recall benchmark remain open. |
| R4 Backup, restore and migrations | NOT RUN | No independent canonical/artifact/workflow/control restore, owner-key recovery or measured RPO/RTO evidence. |
| R5 Local-to-VPS transfer | NOT RUN | No locked release image, HTTPS deployment, single-authority handover, remote native workflow or rollback evidence. |
| R6 Release coverage | NOT RUN | P0 rows remain partial or not run; release traceability, runbooks and full evidence review are unfinished. |
## PRD P0 requirement status
This requirement-level view complements milestone gates. `COMPLETE` means local feature acceptance has evidence; it does not imply pilot, target-client or deployment acceptance. P0 rows stay partial where a required workflow or proof is still missing.
| Requirement | Status | Evidence and remaining proof |
| --- | --- | --- |
| FR-P1 Project registry lifecycle | COMPLETE | Authorized project listing is implemented; authenticated non-agent administrators can create projects with a named owner and matching initial policy, and archive projects. Project and policy records publish together at the PRD canonical paths in one Git commit; archives retain history and block new acceptance while preserving reads. Tests cover HTTP roles, browser CSRF/origin, body limit, duplicate IDs, create/archive idempotency, provider loading and writer-lock contention (`tests/api/test_project_admin.py`, `tests/application/test_registry.py`, `tests/domain/test_validation.py`). Protected owner grants and first-owner bootstrap remain open under FR-P8/M1.1. |
| FR-P2 Explicit scope | COMPLETE | Scope distinguishes omitted `include_projects` from an explicit list: search, neighbors and source reads resolve one project context's `default_includes` plus shared, while an explicit empty list selects only the context project. Authorization checks cover every expanded project; all-project access remains explicit. HTTP/MCP integration proves default and explicit-empty behavior for search, neighbors and source lists, rejects unauthorized default and explicit includes, and checks scoped citations plus direct node/source reads (`tests/api/test_scope_resolution.py`). Domain, service and API tests cover scoped writes, `all_projects` authorization and principal grants (`tests/application/test_search_scope.py`, `tests/domain/test_contracts.py`, `tests/api/test_search_api.py`, `tests/api/test_mcp_contribution.py`). |
| FR-P3 Shared source/entity dedupe | PARTIAL | Artifact bytes deduplicate by digest without losing project grants; entity aliases and duplicate candidates are indexed, but owner-authorized reversible entity merge is open (`tests/application/test_uploads.py`, `tests/domain/test_validation.py`). |
| FR-P5 Project lens | PARTIAL | Registry records carry north-star/questions and the pack routes ingest/curation through the selected project context; native-host execution and pilot lens usefulness are unverified. |
| FR-P8 Human and agent authority | PARTIAL | Viewer/editor/admin and agent keys, rotation, revocation, browser sessions and publication rechecks are tested. Challenge-bound owner login, isolated owner MCP decisions and manifest-recorded policy exceptions are locally tested. First-owner bootstrap, reset/recovery, actual OS isolation and named pilot owner grants remain open (`tests/adapters/test_sqlite_identity.py`, `tests/api/test_owner_session.py`, `tests/application/test_acceptance.py`). |
| FR-I1 Source intake | PARTIAL | URL, selected-file, pasted-text, timestamped transcript and Linux PDF capture paths exist. Authenticated `source_capture_text` stores bounded UTF-8 text/Markdown as a private artifact, extracts it, and returns a proposal-ready source candidate marked `pasted-text`; a stable capture ID enables exact retries from a private bounded receipt journal, while source registration still requires the normal typed proposal. Supplied NotebookLM export workflows and native-host qualification remain (`tests/adapters/test_pdf_extractor.py`, `tests/adapters/test_url_fetch.py`, `tests/api/test_mcp_contribution.py`; [pasted-text evidence](2026-10-14-pasted-text-capture.md)). |
| FR-I2 Immutable source revisions | PARTIAL | Digest-bound revisions, immutable artifacts, retry and shared byte dedupe are tested. Real URL/source identity matching and pilot source coverage remain open (`tests/application/test_uploads.py`, `tests/api/test_stdio_connector.py`). |
| FR-I3 Lens triage | PARTIAL | The agent pack instructs lens-based relevance decisions; semantic scoring/reason quality has no labeled pilot evaluation (`agents/gewu/skills/kb-ingest/SKILL.md`, M3.4). |
| FR-I4 Evidence-backed digestion | PARTIAL | Typed proposals require claim evidence and exact locators; a synthetic source-to-citation flow passes. Real-source semantic coverage remains open (`tests/domain/test_validation.py`, `tests/api/test_mcp_contribution.py`, M0.3/M3.4). |
| FR-I6 Entity linking and reversible merges | PARTIAL | NFC aliases, authorized duplicate nomination, typed links and contradiction preservation are implemented; reversible merge history and protected owner workflow remain open (`tests/domain/test_validation.py`, M2.4). |
| FR-I7 Quote and support verification | COMPLETE | Archived revision digest, extraction integrity, exact quote location, assessment attribution and required support policy are checked; invalid evidence cannot publish (`tests/domain/test_validation.py`, `tests/api/test_mcp_contribution.py`). Pilot semantic assessor quality remains M3.4. |
| FR-I8 Proposal staging and run log | COMPLETE | Mutations flow through proposal submission; durable run create/checkpoint/status and proposal receipts are covered (`tests/application/test_runs.py`, `tests/api/test_mcp_contribution.py`). Native workflow execution remains M2.5. |
| FR-I9 Ingested-for provenance | COMPLETE | Shared artifact dedupe retains both project grants and denies an ungranted project (`tests/application/test_uploads.py`, `tests/api/test_authenticated_read.py`). |
| FR-I11 Durable external runs | PARTIAL | Private bounded run state, revision-checked checkpoints, receipt identity, revocation and recovery are tested. Native-agent interruption/resume is unverified (`tests/application/test_runs.py`, `tests/api/test_mcp_contribution.py`, M2.5). |
| FR-V1 Validation | COMPLETE | Schema, scope, relationship, exact evidence and assessment checks run before publication; failed proposals remain staged (`tests/domain/test_validation.py`, `tests/application/test_acceptance.py`). Semantic reviewer quality is tracked in M3.4. |
| FR-V2 Proposal correction and exceptions | PARTIAL | Evaluate/submit/status/withdraw and policy acceptance are integrated; policy-only holds can be authorized through exact-diff owner challenges and acceptance manifests. Duplicate merge and reversible merge workflows remain incomplete (`tests/api/test_mcp_contribution.py`, M1.1/M2.4). |
| FR-V3 Policy-controlled acceptance | COMPLETE | Every affected policy must permit acceptance; mandatory schema/scope/evidence/support checks cannot be waived, and eligible fixtures publish without human review (`tests/domain/test_validation.py`, `tests/application/test_acceptance.py`). Owner-protected exceptions remain under FR-P8. |
| FR-V4 Contradiction lifecycle | PARTIAL | Contradictory claims and typed links are preserved; curator detection and end-to-end supersession/contradiction workflows need pilot qualification (M2.4/M3.4). |
| FR-V5 Durable proposal lifecycle | COMPLETE | Proposal revisions, correction invalidation, idempotent receipt, conflict, withdrawal and crash recovery are tested (`tests/application/test_acceptance.py`, `tests/application/test_runs.py`). |
| FR-A1 Typed agent/read APIs | COMPLETE | Catalogued MCP tools cover scoped reads, source intake and proposal/run operations; the HTTP API exposes reads and control diagnostics without knowledge mutation (`tests/api/test_openapi_contract.py`, `tests/api/test_agent_contract.py`). |
| FR-A2 Hybrid retrieval | PARTIAL | Configured search uses scoped vector retrieval, RRF and capped one-hop typed-edge expansion with citations; keyword mode remains the default unless a local model path and digest are configured. Unit/integration and real-model composition probes pass. The PRD's labeled top-five recall target and required packaging/language qualification remain unverified (`docs/acceptance/2026-10-14-hybrid-probe.md`). |
| FR-A3 Bounded citation responses | PARTIAL | Full serialized payload counting, citation-group truncation, omission/warning retention and too-small 413 behavior are tested. The codepoint counter is provisional, not the final tokenizer profile (`tests/adapters/test_sqlite_search.py`, `tests/api/test_search_api.py`, M1.4). |
| FR-A5 Enforced contribution boundary | PARTIAL | Service credentials and canonical data are separated from proposal APIs, and direct HTTP knowledge writes are absent. Restricted mounts and authority handover require deployment evidence (R1/R5). |
| FR-A6 Harness integration | PARTIAL | Canonical profile and reversible AGENTS/CLAUDE/GEMINI pointers install without overwriting unrelated files; host MCP configuration and OpenCode/Claude/Codex/Antigravity discovery are unqualified (`tests/test_pack_installer.py`, M2.2/M2.5). |
| FR-A9 Typed-only tools | COMPLETE | MCP exposes catalogued typed operations with no raw SQL/Cypher; proposal writes are typed and staged (`tests/api/test_agent_contract.py`, `tests/api/test_catalog.py`). |
| FR-A10 Client diagnostics | PARTIAL | Diagnostics report authenticated capability, scope, catalog, limits and index status without secrets; native-client configured/connected/workflow-verified evidence remains M2.5. |
| FR-A11 GEWU workspace pack | PARTIAL | Manifest-bound profile, protocols, skills, pipelines, service snapshot and resumable checkpoints verify locally. Native host workflows and cross-agent convergence remain M2.5. |
| FR-C3 Staleness | COMPLETE | API warnings and URL-backed stale filtering are tested; the reader presents stale state (`tests/adapters/test_sqlite_search.py`, `tests/api/test_search_api.py`, M3.2). |
| FR-U1 Project/shared navigation | PARTIAL | Authorized project selection and shared-scope controls exist; an all-project browsing view with complete cross-project markings needs qualification (M3.2/M3.3). |
| FR-U2 Search filters | COMPLETE | Type, audience, domain, project, confidence and inclusive `as_of` date-range filters execute in scoped SQLite search, bind into cursors, persist in URLs and restore after authentication. HTTP/MCP, database, reader and Chromium coverage pass (`tests/adapters/test_sqlite_search.py`, `tests/api/test_search_api.py`, `web/src/shell/App.test.tsx`, `web/e2e/reader.spec.ts`). |
| FR-U3 Node/source reading | PARTIAL | Accepted nodes, citations, archived source downloads/locations, typed neighbors and bounded history are connected. Source-to-citing-note navigation and real reading tasks remain unqualified (M3.2/M3.4). |
| FR-U6 Staleness view | PARTIAL | Stale warnings and a URL-backed stale-only shortcut exist; a fully evaluated read-only stale knowledge list remains part of UI acceptance (M3.1/M3.4). |
| FR-U9 Problem/topic reading | PARTIAL | Scoped problem browsing, accepted approaches, assumptions/limitations, source references and labeled suggestions exist. Cross-project explanations and visual/accessibility acceptance remain open (M3.3). |
No pilot or v1 completion claim is supported by this ledger. Continue closing locally testable rows and record owner-, corpus-, host-, or deployment-dependent evidence when those inputs become available.
@@ -0,0 +1,35 @@
{
"benchmark": "sqlite-search-adapter-synthetic-v1",
"environment": {
"logical_cpus": 8,
"platform": "Linux-7.2.5-3-omarchy-x86_64-with-glibc2.44",
"processor": "Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz",
"python": "3.14.7",
"sqlite": "3.53.4"
},
"evidence_scope": "synthetic adapter benchmark; excludes HTTP/auth, Git object reads, and semantic relevance",
"limitations": [
"synthetic records reuse one valid claim/citation shape and are not a relevance corpus",
"in-memory canonical reads omit Git filesystem and HTTP/API overhead",
"the PRD hardware, cache state, concurrency, and percentile decisions are not fixed"
],
"measurements": {
"cold_index_rebuild_and_first_search_seconds": 43.55,
"first_result_count": 20,
"synthetic_seed_seconds": 0.214,
"warm_search_ms": {
"max": 28.418,
"p50": 23.805,
"p95": 26.681
}
},
"workload": {
"nodes_per_project": 10000,
"page_size": 20,
"projects": 1,
"query": "interactive visitors",
"query_project": "bench-project-000",
"total_nodes": 10000,
"warm_samples": 30
}
}
@@ -0,0 +1,35 @@
{
"benchmark": "sqlite-search-adapter-synthetic-v1",
"environment": {
"logical_cpus": 8,
"platform": "Linux-7.2.5-3-omarchy-x86_64-with-glibc2.44",
"processor": "Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz",
"python": "3.14.7",
"sqlite": "3.53.4"
},
"evidence_scope": "synthetic adapter benchmark; excludes HTTP/auth, Git object reads, and semantic relevance",
"limitations": [
"synthetic records reuse one valid claim/citation shape and are not a relevance corpus",
"in-memory canonical reads omit Git filesystem and HTTP/API overhead",
"the PRD hardware, cache state, concurrency, and percentile decisions are not fixed"
],
"measurements": {
"cold_index_rebuild_and_first_search_seconds": 422.283,
"first_result_count": 20,
"synthetic_seed_seconds": 2.024,
"warm_search_ms": {
"max": 144.37,
"p50": 132.549,
"p95": 144.37
}
},
"workload": {
"nodes_per_project": 10000,
"page_size": 20,
"projects": 10,
"query": "interactive visitors",
"query_project": "bench-project-000",
"total_nodes": 100000,
"warm_samples": 10
}
}
+13 -7
View File
@@ -1,6 +1,6 @@
# Acceptance, authority and evidence contract
Status: proposed v0.2 after [independent review](../reviews/ARCHITECTURE_SENIOR_REVIEW.md). Drafted 12 October, revised 13 October 2026. Implements the boundaries in the [architecture](ARCHITECTURE.md); schemas and executable tests are still required at M0.
Status: proposed v0.2 after [independent review](../reviews/ARCHITECTURE_SENIOR_REVIEW.md). Drafted 12 October, revised 14 October 2026. Implements the boundaries in the [architecture](ARCHITECTURE.md). Initial record/API schemas and executable tests exist; the full PRD contract audit remains open.
## Record separation
@@ -39,7 +39,13 @@ Named initial operations are `search`, `get_node`, `neighbors`, `list_projects`,
## Scope and policy domains
Reads resolve requested projects plus their declared includes and shared. An `all` request is explicit. Direct IDs, redirects, source citations, graph neighbors and suggestions honor the resolved scope. When a target is outside scope, return an omission reason and a way to request wider scope. Never silently follow a link into another project.
Reads resolve a single project's `default_includes` plus shared when `include_projects` is omitted. An explicit (possibly empty) `include_projects` list replaces those defaults. Multiple explicit project contexts and an `all` request do not inherit per-project defaults; all-project access remains explicit. Every project in the expanded scope and shared library must be authorized. Direct IDs, redirects, source citations, graph neighbors and suggestions honor the resolved scope. When a target is outside scope, return an omission reason and a way to request wider scope. Never silently follow a link into another project.
## Project registry lifecycle
Project IDs are immutable lowercase hyphen-separated slugs. The canonical project entry is `projects/<project_id>/project.md` with a strict YAML frontmatter `ProjectRecord`; its initial `AutoAcceptPolicy` is published in the same Git commit under `policies/<sha256(policy_id)>.yaml`. Project creation requires a named owner, a matching policy ID/project ID, supported-assessment enforcement, and default includes that resolve to existing projects or shared. A duplicate project or policy ID conflicts; project IDs are never reused.
Only an authenticated non-agent administrator can list full project records, create a project, or archive one. These HTTP control-plane operations are separate from agent/MCP knowledge contribution. Browser-session writes require same-origin and CSRF checks. The project-record and policy publication uses the canonical writer lock and expected-head commit so proposal validation cannot race an archive. Archive is idempotent, writes a new canonical revision, retains all previous records and citations, and cannot be reversed through this API. `active` projects accept eligible proposals; `paused` and `archived` projects remain readable but reject new accepted changes. The reserved shared scope cannot be created or archived as a project. Admin authority does not substitute for the protected owner challenge required for owner-only intent, policy-exception, merge, delete or promotion decisions.
Mutation authority follows every changed record. A project owner does not gain control of shared records or another project's records through a read include. Shared has an explicit owner grant and policy.
@@ -110,19 +116,19 @@ Proposed protected-action flow:
3. The human confirms there. The owner client submits a decision through MCP; the service checks project/shared ownership and records a single-use authorization bound to proposal revision, digest, policy versions and expiry.
4. The service revalidates and accepts when every affected domain permits it. Changed content, changed authority/policy, expiration or withdrawal invalidates the decision. The agent receives status only and never receives owner credentials.
An admin bootstraps accounts, key issuance and owner grants through a separate operator control plane. This authority alone cannot bypass a protected knowledge decision. Owner decisions and their audit references survive index deletion. The account/bootstrap commands are proposed tooling, not currently runnable commands.
An admin bootstraps accounts, key issuance and owner grants through a separate operator control plane. This authority alone cannot bypass a protected knowledge decision. Owner decisions and their audit references survive index deletion. The local `gewu-owner` command provisions an owner interactively, writes only an Argon2id password hash and encrypted TOTP seed, records a security event, and prints the enrollment URI once to a TTY. It is a local operator primitive; no owner accounts or grants are provisioned in this workspace.
Isolation is a deployment fact. If the agent can execute as the owner and read the owner's secrets, this mechanism cannot prove human-only authorization. Use a separate OS principal/device or a protected interactive authenticator before claiming that gate passed. Do not invent human approval from conversational text supplied by the agent.
### Proposed owner authentication profile
Use the controlled GEWU owner CLI over HTTPS to the same service's Streamable HTTP MCP endpoint. Before MCP initialization, the CLI calls a separate `POST /auth/owner-session` control endpoint with human account ID, password, TOTP and challenge ID. Password/TOTP are read directly from the human terminal without echo, never arguments/environment variables, and discarded after use. The server verifies a maintained Argon2id password hash and TOTP with a pinned library (proposed `argon2-cffi` and `pyotp`), rate limits failures and prevents reuse of an accepted TOTP timestep. Enrollment/reset requires restricted operator identity and records a security event. TOTP seeds are encrypted under a service key kept outside the database and ordinary data-backup set. Maintain that key in a separately protected, encrypted, access-controlled recovery backup. A restore verifies the key before enabling owner operations; if unavailable, owner login stays disabled until an attributable operator reset and human re-enrollment complete. Test both recovery paths before team release.
Use the controlled GEWU owner CLI over HTTPS to the same service's Streamable HTTP MCP endpoint. Before MCP initialization, the CLI calls a separate `POST /auth/owner-session` control endpoint with human account ID, password, TOTP and challenge ID. Password/TOTP are read directly from the human terminal without echo, never arguments/environment variables, and discarded after use. The server verifies an Argon2id password hash and TOTP with `argon2-cffi` and `pyotp`, limits failed attempts, prevents reuse of an accepted TOTP timestep, and binds login to an unexpired issued challenge. Enrollment records a security event; reset and recovery workflows remain unimplemented. TOTP seeds are encrypted with Fernet under `GEWU_OWNER_ENCRYPTION_KEY`, kept outside the database and ordinary data-backup set. Maintain that key in a separately protected, encrypted, access-controlled recovery backup. A restore verifies the key before enabling owner operations; if unavailable, owner login stays disabled until an attributable operator reset and human re-enrollment complete. Test both recovery paths before team release.
On success, generate a random 256-bit opaque token, store its hash in the private control database, and return it once with a five-minute expiry. Store the human principal, current grant version, service audience, allowed challenge ID and capabilities `owner:inspect`/`owner:decide`. The CLI keeps the token in memory and presents it as the MCP bearer credential; it is rejected by ordinary browser sessions and agent-key validation paths. The token cannot create arbitrary proposals or authorize another challenge. Reauthentication is required after expiry. Network operations verify TLS and the configured service identity. This custom profile is explicitly limited to GEWU's controlled clients and makes no general OAuth-interoperability claim.
On success, generate a random opaque token, store its hash in the private control database, and return it once with a five-minute expiry. Store the human principal, current grant version, service audience and allowed challenge ID. The token is rejected by ordinary browser sessions and agent-key validation paths. The dedicated `/owner-mcp` surface exposes challenge metadata, the complete digest-checked diff, and an immutable authorize/reject operation. Reauthentication is required after expiry. Network operations verify TLS and the configured service identity. This custom profile is explicitly limited to GEWU's controlled clients and makes no general OAuth-interoperability claim.
MCP operations: `owner_challenge_get(challenge_id)` returns proposal revision/digest, affected domains/policy versions, expiry and status; `owner_diff_get(challenge_id)` returns the exact bounded diff and its digest; `owner_decide(challenge_id, expected_proposal_revision, expected_payload_digest, expected_diff_digest, decision, rationale)` accepts an attributable authorize/reject decision after rechecking current grants. Oversized diffs must be fully paginated and hash-bound before confirmation; they cannot be silently truncated.
MCP operations: `owner_challenge_get(challenge_id)` returns proposal revision/digest, affected domains, expiry and status; `owner_diff_get(challenge_id)` returns the complete bounded diff and its digest; `owner_decide(challenge_id, expected_proposal_revision, expected_payload_digest, expected_diff_digest, decision, rationale)` records an attributable authorize/reject decision after rechecking current grants. The current implementation caps a challenge diff at 512 KiB and refuses to create or return a larger diff; it never silently truncates one. Pagination remains future work if real pilot diffs exceed this bound.
Challenges live in the control database with states `issued`, `authorized`, `consumed`, `expired` or `invalidated`, plus immutable transition events. Only an unexpired `issued` challenge can acquire an immutable owner decision. Exact decision retries return the same decision; altered retries fail. Multiple owners can supply separate decisions for a bundle, each bound to its domains. An authorization is consumed by one acceptance manifest containing the full non-secret decision snapshot and digest. The global writer/recovery gate ensures the manifest is checked before any decision can be reused. A crash before the SQLite consumed flag is updated is recovered from that manifest; a missing flag cannot permit another acceptance. Rejection invalidates the challenge and records its decision without publishing the proposed knowledge.
Owner challenge bindings are persisted with the proposal revision/digest, diff digest, affected domains, grant version and expiry. Challenge issue retries are idempotent and changed content conflicts; expired, out-of-grant and decided challenges cannot create new owner sessions. Policy-only proposals generate a challenge per named owner and affected domain set. Acceptance revalidation checks that authorized challenges still match the current proposal, diff, policy versions and owner grants, and that their combined domains cover the bundle. The canonical manifest records immutable decision references; an accepted proposal's manifest and receipt prevent decision replay after publication. Explicit `consumed`/`invalidated` lifecycle rows, crash-injection across control-store reconciliation, reset/recovery and OS-level owner isolation remain open.
Contract tests must cover owner session used as an agent token, browser/agent token used for owner operations, expired/wrong-audience token, revoked grant, TOTP reuse, altered diff, duplicate decision and crash-before-consumed-state. The profile remains proposed until implemented and reviewed on the actual client/service deployment.
+3 -1
View File
@@ -114,6 +114,8 @@ Every content query carries scope. Resolve registered projects and their explici
Search runs scope-filtered FTS and vector candidates, merges them with reciprocal rank fusion, and performs bounded typed-edge expansion. Start with a maximum one-hop expansion and explicit candidate/edge caps in the public contract. Return ranking explanations separately from evidence status. Related suggestions never become accepted relationships by indexing.
The local service stays in keyword mode unless `GEWU_EMBEDDING_MODEL_PATH` and `GEWU_EMBEDDING_MODEL_SHA256` are both set. The configured path must point to an already-installed model tree; inference is local-only with remote code disabled. `GEWU_EMBEDDING_MODEL_ID` defaults to the pinned multilingual E5 candidate and `GEWU_EMBEDDING_DIMENSIONS` defaults to 384. Install the `retrieval` extra to enable the optional runtime. Missing or failed vector generations produce a labeled keyword response. See the [probe and setup evidence](../acceptance/2026-10-14-hybrid-probe.md). This opt-in runtime is not a full-v1 acceptance claim.
Use normalized English token search plus language fixtures. `unicode61` alone is not a claim of Chinese word segmentation; test CJK queries and use a documented segmentation or trigram adapter when needed. Evaluate short queries separately. Search acceptance is the PRD's labeled per-project question set, not a synthetic speed result.
Index updates publish all node/edge/FTS/vector changes for a chosen Git revision in one SQLite transaction. Queries use a read transaction pinned to an index revision. A model change builds a separate index generation, with model ID, artifact hash, dimensions, normalization, chunking and parser versions. Publish the new generation only after integrity and retrieval gates pass. Avoid replacing an open database file on Windows: switch the service's generation pointer and retire old connections before cleanup. The acceptance contract specifies the immutable extraction artifact and rebuild watermark procedure.
@@ -166,5 +168,5 @@ Checked 12 October 2026. These sources establish available mechanisms, not GEWU
- [FastAPI process workers](https://fastapi.tiangolo.com/deployment/server-workers/): multiple workers are separate processes; an in-process lock cannot serialize their writes.
- [Pydantic strict validation](https://docs.pydantic.dev/latest/concepts/strict_mode/), [Vite](https://vite.dev/guide/), [TanStack Query](https://tanstack.com/query/latest/docs/framework/react/overview): typed boundaries, static assets and server-state tooling supporting the choices above.
- [pypdf extraction limitations](https://pypdf.readthedocs.io/en/stable/user/extract-text.html): extraction and OCR are different capabilities; quality must be measured.
- [Sentence Transformers model loading](https://www.sbert.net/docs/package_reference/sentence_transformer/model.html) supports pinned revisions and local-only loading. The [multilingual-e5-small model card](https://huggingface.co/intfloat/multilingual-e5-small) was available in search results; direct retrieval failed, so its full configuration/license remains a mandatory probe rather than a verified selection.
- [Sentence Transformers model loading](https://www.sbert.net/docs/package_reference/sentence_transformer/model.html) supports pinned revisions and local-only loading. A disposable Linux/Python 3.14 CPU probe loaded the pinned [multilingual-e5-small model card](https://huggingface.co/intfloat/multilingual-e5-small/blob/614241f622f53c4eeff9890bdc4f31cfecc418b3/README.md) snapshot and sqlite-vec 0.1.9; see the [probe record](../acceptance/2026-10-14-hybrid-probe.md). The adapter is implemented, but vector storage/fusion, offline distribution, native cross-platform compatibility and labeled recall remain unqualified. sqlite-vec remains pre-v1 and is not yet approved as the production index backend.
- [tiktoken](https://github.com/openai/tiktoken) provides named encodings for a reproducible budget convention. [Git update-ref](https://git-scm.com/docs/git-update-ref.html) supports an expected-old object check for publication.
+3 -1
View File
@@ -19,8 +19,10 @@ The intended installed layout resembles the RESEARCH workspaces:
```text
<research-workspace>/
AGENTS.md # thin discovery pointer to canonical profile
CLAUDE.md # thin discovery pointer for Claude Code / Claude Desktop
.agents/
AGENTS.md # GEWU role and routing
CLAUDE.md # Claude harness pointer
manifest.json # pack/skill/pipeline versions and readiness
protocols/ # shared evidence, scope and proposal rules
skills/<name>/SKILL.md
@@ -56,7 +58,7 @@ The [modularity protocol](../development/MODULARITY_PROTOCOL.md) applies to all
| `kb-curate` | Scoped audit -> inspect candidates -> propose corrections/relations -> receipts | Traceable changes or a report, preserving disagreements and old revisions. |
| `kb-synthesize` | Accepted inputs -> dependency inventory -> compare/compose -> evidence audit -> optional proposal | Labeled local synthesis draft, or accepted synthesis after a real receipt. |
The four skills are instruction artifacts in this change. Service schemas, executable tools and client acceptance remain unimplemented. The manifest declares no verified service compatibility yet. The pack can organize explicitly requested local drafts; it must report the missing service instead of fabricating tool calls, source revisions or accepted knowledge.
The four skills are instruction artifacts, and the service has authenticated Streamable HTTP reads and contribution tools. The `gewu-connector` stdio program bridges explicitly selected local files to that service without exposing file bytes or credentials in model-visible tool responses. It is launched with one or more stable file IDs and paths, plus a service URL; the operator supplies `GEWU_TOKEN` through the host's protected environment rather than a command-line argument. The connector requires HTTPS for non-loopback services and stores resumable upload checkpoints in a private state file. The pack manifest is bound to generated wire schemas and now has a reversible workspace installer, but host MCP configuration, native client workflows and remote deployment remain unqualified. The authenticated `source_capture_url` MCP operation is enabled only when the operator configures the exact public-host allowlist in `GEWU_FETCH_ALLOWED_HOSTS`; URL and selected-file intake support UTF-8 text, Markdown, HTML visible-text extraction and PDF. Linux PDF extraction runs inside bubblewrap; scanned PDFs return an explicit no-text result, and Windows/macOS parsing remain unqualified.
## Run and resume contract
@@ -0,0 +1,34 @@
# ADR-001: Human administrator credential panel
Status: implemented, 14 October 2026.
The service now exposes a separate `/admin` web page for human administrators to list,
create and revoke bearer credentials and read recent credential-management activity.
The research library's knowledge remains read-only in the browser.
The panel reuses the existing human browser session and admin role. Agent identities,
including identities holding both agent and admin roles, cannot administer credentials.
Browser writes require the session CSRF token and same-origin requests. Credential
responses use `Cache-Control: private, no-store`; only creation returns the new secret.
The panel holds secrets in memory, never browser storage. Revoke confirmation names the
key, and the service rejects revocation of the key backing the caller's current session.
The strongest alternative was retaining CLI-only provisioning. That avoids a network
credential-management surface but does not provide the requested operator workflow.
The first administrator still requires local operator provisioning; the panel cannot
bootstrap anonymous access. Owner review authentication remains separate.
An additive `admin_events` SQLite table records time, actor, action and credential ID.
The event and its successful credential mutation commit in one transaction. No raw
secrets, digests, source bodies or arbitrary application log messages enter this table.
The initial log covers panel/API creation and revocation only; CLI actions and historical
credentials are not backfilled. Runtime logs and agent run history remain outside this
first slice. Credential listing is paged; activity is limited to the latest 50 events.
Existing credentials and sessions require no migration. Reverting the UI and routes
leaves the additive table harmlessly in place. Credentials issued through the panel
remain usable by the existing identity store and can be revoked locally.
Validation: API authorization, CSRF, origin, request bounds, conflicts, secret omission,
durable audit, bearer/session revocation, frontend credential creation and confirmation
flows. Rendered checks use a disposable data root, separate from operator state.
@@ -0,0 +1,59 @@
# ADR-002: Password accounts and personal agent keys
Status: implemented, 14 October 2026.
Human users sign in with a username/password through `/v1/users/session`. Agent hosts
continue to use independent, high-entropy bearer keys. This replaces bearer-key-only
human login as the default UI while retaining the existing operator key for initial
account setup and recovery. Protected owner review remains a separate password/TOTP,
challenge-bound workflow.
Administrators create and disable accounts with viewer, editor or admin roles and
project grants. Editors and administrators issue keys for their own agents at
`/v1/me/agent-credentials`; viewers retain read-only access. The server derives the
owner from the authenticated account and checks requested grants against current
account grants in the same database transaction as issuance. An agent has its own
principal identity for proposals/runs. Users can only list and revoke their own keys.
Administrators can still inspect and revoke all keys.
Passwords are hashed with the existing Argon2id implementation. Login uses an
HttpOnly, SameSite=Strict session cookie, with Secure on HTTPS. Public password login
requires HTTPS; localhost is allowed for development. Browser writes require CSRF
and the existing same-origin validation. The development proxy preserves the public
Host, allowing TLS-terminating deployments to validate the browser's actual Origin.
Forwarded scheme handling remains Uvicorn's trusted-proxy responsibility; application
code does not trust arbitrary forwarding headers.
Five failed logins for a username within 15 minutes block further attempts until
that window expires. A shared 100-failure window bounds random-username attempts.
Unknown/disabled usernames use a dummy Argon2 verification and generic failure text.
This initial limiter favors a small private service; shared lockouts can be abused
for denial of service. Larger deployments should add an edge rate limiter.
Page loads restore existing human browser sessions through `GET /v1/session` with
an explicit same-origin client header. The endpoint returns expiry, a CSRF token and
account kind; it never returns the session cookie or bearer key. A stable one-way
CSRF token is derived from the private session secret and its digest is saved beside
the original CSRF digest. This additive migration preserves pre-upgrade sessions and
old tabs, while preventing reloads or simultaneous tabs from invalidating each other.
Restoration does not extend the original session lifetime. No browser storage is used.
Changing a password requires the current password, invalidates every browser session
for that account, and preserves independent agent keys. Disabling an account revokes
its login identity and its agent keys atomically under the canonical authority lock.
Activity events include account creation, disable and password changes, without
passwords or bearer secrets. Sensitive validation errors omit submitted inputs.
The strongest alternative is external OIDC/SSO. It avoids local password management
but adds an external identity dependency beyond the requested minimal private-service
workflow. There is no anonymous registration or email recovery in this slice.
Migration is additive: `user_accounts`, login failure tracking, and a nullable owner
column on credentials. Existing bearer keys and browser sessions continue to work.
Account login identities have an unrecoverable random bearer digest; only password
sign-in creates their sessions. Rolling back the routes/UI preserves existing keys;
new human accounts require the updated identity implementation.
Validation covers login/CSRF/TLS/body limits, password hashing and changes, session
invalidation, user ownership, grant escalation, agent/human separation, disabled users,
login throttling, preserved existing credentials, UI setup and personal key issuance.
+7 -1
View File
@@ -34,7 +34,13 @@ Keep scope, search query, filters and selected node/revision in the URL. Browser
Cancel obsolete requests or ignore their results, including obsolete loading and error states. Query polling exists only for a visible need and cannot overlap indefinitely. Avoid a global real-time event system before the product requires it.
Fetch through the typed API layer. Components receive enough data to render complete states: loading, empty, unavailable, forbidden, stale, index-lagged and successful. A valid empty search is different from a failed request. Profile before adding broad memoization or custom comparison functions. Sanitize Markdown rendering and scope reading typography so source headings cannot restyle navigation.
Fetch through the typed API layer. Components receive enough data to render complete states: loading, empty, unavailable, forbidden, stale, index-lagged and successful. A valid empty search is different from a failed request. Apply the shared component and rendering guidance below. Sanitize Markdown rendering and scope reading typography so source headings cannot restyle navigation.
### Shared UI modules and render performance
Build repeated administration and reading patterns from application-owned components with small contracts: labels, data props, actions, loading/empty/error states and focus behavior. Keep feature-specific data fetching and mutations in the owning feature module; shared primitives own presentation and interaction mechanics. Use semantic lists for repeated records and a shared dialog primitive for add/edit flows so focus trapping, Escape handling and focus restoration stay consistent. Reuse token-based styles rather than cloning one-off control styles.
Keep state in the smallest feature that needs it so typing or selection does not rebuild the whole application shell. Give mapped records stable keys. Keep callbacks and derived props stable where a memoized feature boundary depends on them. Use `React.memo` for measured or structurally expensive subtrees with stable props, and `useMemo`/`useCallback` for costly derivation or identity-sensitive boundaries; avoid blanket memoization and custom equality code without a profile. Preserve mounted DOM only when it protects useful form or navigation state, and avoid rendering large hidden collections unnecessarily. Use virtualization only after measurement shows a list exceeds practical DOM cost. Verify actual rerender reduction with React profiling when optimizing a hot path.
## Verification proportional to the change
+1 -1
View File
@@ -63,4 +63,4 @@ At scaffolding, add import/dependency checks and reusable contract test suites f
Early acceptance examples: swap an embedding provider and rebuild without changing search consumers; substitute an extraction-stage implementation while preserving old citations; replace a frontend evidence panel without changing the read API; resume an agent run with its original pinned skill version after a newer version is installed. These are required design tests to implement, not existing passes.
Primary documentation above was checked on 13 October 2026. No module implementation or replacement test exists yet.
Primary documentation above was checked on 13 October 2026. The canonical repository port now owns its stable errors, path rules, revision-history semantics and a shared behavioral contract run against both the Git adapter and an independent in-memory implementation. `CanonicalNodeReader` also returns the same accepted node and citations against the substitute without consumer changes. This demonstrates dependency isolation and the checked contract subset; it does not establish durability, locking, crash recovery or production equivalence for another backend. Broader fault, concurrency and filesystem-specific qualification remains required.