Skip to content

Maintained work

Source reports, source-version checks, stale results, and repair review.

The Work screen creates a report from approved local text and Markdown sources. It uses keyword retrieval and quotes source passages. It does not call a model, execute source instructions or independently prove the statements in a source.

Work also offers source-linked briefs, which use an explicitly selected local model and a separate citation checker. Excerpt reports keep the behavior described below. Both result types use the same durable revisions, source-access checks, repair approval and restore rules.

Create a report

Complete local setup and approve a folder. Open Work, enter a query and create a source report. The worker searches at most 2,000 files for up to 30 seconds. It reads at most 256 KiB per file and keeps up to six matching excerpts. The result records whether the scan reached a limit. A scan with no matches fails clearly.

The status Sources checked means that the stored source versions matched when checked. It does not mean that all claims in the report are true.

The local worker stores tasks and reports in work.sqlite under the instance directory. A task continues when the page closes. After a process crash, an expired worker lease allows another process to resume this read-only task. An old worker cannot publish after its lease expires or after cancellation.

Respond to a source change

The worker checks tracked sources at intervals and when the result is opened. A changed or missing source marks dependent reports stale. Other reports keep their status. Removed access hides the cached content from the API.

Choose Prepare repair to repeat the query against current approved sources. The proposal shows the accepted result, proposed result and difference. It does not change the accepted result. Apply repair approves that exact proposal. The server checks the content fingerprint, current revision, source versions, expiry and prior use in one database transaction. A proposal expires after one hour. A changed result or source requires a new proposal.

Restore an earlier result

Open Sources & history and select an earlier revision to compare its saved body with the accepted result. The server captures both bodies and the accepted revision number in one database transaction. The selected revision's source state is calculated from the latest observed source versions.

Choose Prepare restore, review the exact difference and evidence state, then apply the proposal. If revision 2 is accepted and revision 1 is selected, applying the restore creates revision 3 with restored_from: 1. It copies revision 1's content, source dependencies and original checks, including the original check timestamp. All existing revisions remain in storage. Restoring a result does not change source files or run the query again.

An accessible source that differs from the historical version permits a stale restore. Restoring old text does not make its old evidence current. If the historical versions match the latest observations, the result is Sources checked; the original check timestamp and verification limits still remain. Missing evidence or removed access prevents restore. In that case the revision comparison and restore proposal hide the saved body, references, checks and difference. This includes inaccessible sources required by the accepted body shown in the comparison, even when the selected revision's sources remain accessible.

The approval binds the proposal ID, local workspace and owner, exact accepted revision and body, chosen historical revision, copied content, source dependencies, checks, observed source versions and one-hour expiry. The server checks the same fields again when applying. A changed accepted result, changed observations, expired approval or reused fingerprint produces a conflict and leaves the accepted revision intact. Applying, recording the new revision, consuming the approval and writing its audit event share one SQLite transaction. A storage failure rolls back that transaction.

Retrying the same restore returns its existing pending proposal and original expiry. Preparing a different restore or preparing again after observed sources change supersedes the earlier pending restore for that result. Its approval metadata remains in storage, but its fingerprint can no longer be applied. There is at most one pending restore per result and 20 unexpired pending restores per workspace. Used or expired approvals are never reused.

Source refresh happens before the transaction. It is a bounded series of file reads, not an atomic filesystem snapshot: files can change after they were read. The transaction binds the recorded observations and stored revisions; it cannot lock source files or establish independent truth. Later refreshes update the result's source state.

History responses include the latest 100 revision entries with restored_from metadata. Earlier stored revisions remain addressable by revision number. This increment has no erasure workflow.

Export saves a JSON source-report record with the result, source versions, verification limits and revision metadata. The export is not digitally signed. It does not establish authenticity or independent verification on another system.

Inspect Work relationships

The maintained Work graph projects the existing SQLite records into sources, source versions, results, revisions, saved verification records, runs and repair/restore proposals. Edges name recorded dependencies and lifecycle transitions. They do not infer semantic relationships or add claim verification. No graph indexer, model, remote service or source-file mutation runs to produce this view. Code-index exploration remains a separate graph capability.

Source-version nodes include versions cited by saved revisions and the currently observed version. This is not an archive of every earlier source file. Check nodes represent saved verification records and retain their original checked_at. Equivalent records can share a node when a restore copies the old evidence. A restore does not become a new check execution. Missing, malformed or oversized verification metadata produces no check node; the revision/proposal has details.verification_available: false, while valid dependencies remain.

The service refreshes only the registered sources in the selected scope. It uses guarded local reads, updates their existing version/access observations, then projects one read-only SQLite transaction. Results, revisions, tasks, proposals and approvals are not changed. Source access is checked again before delivery; a detected loss of access causes redaction and a bounded rebuild. There is no permission cache. These checks cannot lock the filesystem or interrupt every blocked operating-system call. An empty, malformed or oversized saved source location is unavailable in the projection; it cannot inherit cached read authority. Projecting such a record does not replace or repair its saved location.

The response has version: 1, kind: "maintained_work_graph", scope: "local", snapshot, filters, typed nodes and edges, visible summary counts, limits, truncated and omitted. snapshot.id hashes the visible projection; it is stable for unchanged projected records and states. captured_at and observed_at are epoch seconds and are distinct from a saved check's timestamp. The snapshot is neither a filesystem transaction nor signed proof. Node and edge IDs are opaque and ordered deterministically. Every returned edge has both endpoints in the response. Node ref values link to existing result, revision, proposal or run actions. A Work source ID is not a Files API source handle.

Use GET /api/v1/work/graph, optionally focused by one artifact_id or source_id returned by Work. view=attention selects results needing attention and their related records; the default is all. limit accepts integers from 50 to 500, default 250. Duplicate, unknown, malformed or path-like focus parameters are refused with HTTP 400. The encoded query is capped at 1 KiB. Local search and display filters operate on the returned scope.

The projection selects at most 20 results, 128 revisions (16 per result), 64 proposals (16 per result), 100 runs and 128 sources. A source read is capped at 256 KiB. Refresh has the existing cooperative 30-second budget; each SQLite snapshot has a three-second progress/deadline budget and a one-second lock wait. Saved dependency JSON is capped at 16 KiB and verification JSON at 8 KiB, with 64 nesting levels. Larger approval/base/selected records are not passed to the approval validator by this view: their availability requires opening the existing proposal review. The final response contains at most 500 nodes, 1,500 edges and 512 KiB of JSON. The limits object declares these ceilings.

summary counts only the visible selected scope. omitted.bounds and truncated distinguish bounded selection from omitted.inaccessible evidence. An inaccessible result may remain as a generic owned-result stub, but source names, identifiers, digests, cached check details and dependency edges are removed. A revoked current result also hides its revision history. A source focus that is missing, revoked or unknown returns the same empty visible records, counts and omission hints, so focus cannot reveal which reports used a removed source. Graph apply eligibility is informational; the existing exact proposal review and fingerprint-only apply remain the approval boundary.

Run the real-record, migration, permission, transition and HTTP boundary tests with python -m unittest discover -s tests -p "test_work_graph*.py" -v. See managed graphs for the product scope and qualification criteria.

Access boundary

This increment is available only through the authenticated local application. The relay explicitly refuses all /api/v1/work paths. Local handlers also check the socket, origin and relay marker. Browser writes require their local Origin. There is no remote work authorization model in this increment.

Only the worker records source checks. The HTTP API does not accept a client field that declares a report verified. Model output and documents do not grant permissions. Reports are stored artifacts; applying a repair or restore does not overwrite the user's source files or send an external message.

Version 1 API

All responses use Cache-Control: no-store. JSON requests have a 16 KiB body limit and a five-second body deadline. Queries have a 4,000-character limit. The per-workspace pending queue holds at most 20 tasks. Lists return at most 100 entries. The local HTTP workspace is selected by the service, never by a client workspace field.

Method and path Input Result
GET /api/v1/work None Capabilities, worker status, runs, artifacts and recent events
GET /api/v1/work/graph Optional artifact_id or source_id, view, limit Bounded typed Work relationships, source state, saved checks and snapshot metadata
POST /api/v1/work query Queued run; HTTP 202
POST /api/v1/work/runs/{id}/cancel Empty object Cancelled run
GET /api/v1/work/artifacts/{id} None Result, source references, check limits and revision history
GET /api/v1/work/artifacts/{id}/revisions/{revision} Positive integer revision in path Selected revision, captured before, base_revision, before_state, difference, can_restore and restore_problem
GET /api/v1/work/artifacts/{id}/export None Downloadable version 1 JSON report record
POST /api/v1/work/artifacts/{id}/repair Empty object Queued repair; HTTP 202
POST /api/v1/work/artifacts/{id}/restore revision, base_revision as positive integers Stored restore proposal; HTTP 201
GET /api/v1/work/proposals/{id} None Difference, expiry, fingerprint and apply eligibility
POST /api/v1/work/proposals/{id}/apply fingerprint New accepted revision

Restore proposals have kind: "restore", restore_revision, result_state, can_apply and a safe rejection_reason. A source denial returns a redacted revision or proposal with state: "access_removed" or state: "evidence_unavailable". A valid comparison with unavailable evidence returns HTTP 200 and can_restore: false; attempting the restore returns 409. The API accepts no client content, source checks, actor or workspace on restore.

HTTP 400 means invalid input; 401 means missing authentication; 403 means the local access boundary refused the request; 404 means no visible result; 409 means the requested transition is no longer valid; 413 means an oversized body; and 503 means setup or local storage is unavailable.

At most four work requests run concurrently. Excess requests receive HTTP 503. Refresh has a cooperative 30-second budget and fails closed if that budget is exceeded. It cannot interrupt an operating-system file read that is blocked.

The local database uses schema version 2. Opening a version 1 database migrates it in a transaction and preserves its revisions, tasks and events. Existing pending repair fingerprints are rebound to the accepted body and approval actor; review those proposals again after upgrading before applying them. A failed migration leaves version 1 intact for retry. A database created by a newer unsupported application is refused instead of rewritten.

Limits and qualification

This is the first working part of maintained results. It does not implement general autonomous tasks, cloud inference, workflow promotion, independent semantic verification or arbitrary file repairs. Local administrator or same-user operating-system compromise is outside the credential boundary. Database content is private local data and needs a user-approved backup policy.

Remote source reports use a separate explicit folder grant, worker queue and versioned API. The local Work routes above remain local-only.

Tests cover real HTTP execution and restart, cancellation, leases, exact repair approval, revision restore, migration, competing approvals, atomic failure, source invalidation, exclusions and removed access. Fixture tests are not a substitute for clean-device qualification or independent security review.

See the architecture and the release status.