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

+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
}
}