Cite2Site Implementation Specification v0.3
Status: architecture-source implementation contract.
Scope
This specification defines the target behavior for the Cite2Site local CLI and projection engine. It covers authority files, event schemas, adapters, commands, replay, indexing, publication, errors, and validation.
Reading This Specification Correctly
This specification records the v0.3 target architecture. It contains both the implemented first slice and approved subsequent work so that an implementation agent can build without reopening foundational decisions. It must therefore be read with the current status matrix, not as a claim that every listed surface is already available.
Implemented first slice: source-clean text and Markdown selection capture,
append-only citation and handle histories, hash-chain validation, a JSON CLI,
contextual lookup, replay/status with deterministic in-memory indexes,
policy-enforced privacy transforms, grouped JSON export, MkDocs output
with grouped navigation, adapter protocol with conformance harness
(src/c2s/adapter.py, tests/test_adapter_conformance.py),
integration contract (build-docs/architecture/INTEGRATION_CONTRACT.md),
and reference integration examples (examples/integration/).
Target work: richer adapters and native right-click transports. Each target item needs a gate, tests, and status update before it becomes an implementation claim.
Design Argument
Cite2Site separates identity, evidence, presentation, and interaction because these concerns have different failure modes. Immutable citation IDs protect auditability; editable handles preserve usability; replay makes changes in an artifact observable without rewriting history; and projections keep sites and interfaces from becoming hidden authority. The alternative, storing state in markers or editor overlays, would make portability dependent on a particular artifact format or integration.
Requirement Traceability
| Architectural concern | Requirement authority | Primary acceptance evidence |
|---|---|---|
| Source-clean citation capture | BRD BR-001; TR-107 | Source-byte preservation test |
| Append-only evidence and handles | BRD BR-002; TR-102 to TR-106 | Hash-chain and replay tests |
| Contextual action contract | BRD BR-004; DR-001 to DR-004 | Lookup fixture and overlap tests |
| Agent batch behavior | BRD BR-005; TR command requirements | Batch success/error tests |
| Privacy-safe publication | BRD BR-007; TR privacy requirements | Export privacy tests |
| Grouped navigation | DR-007; TR indexing/export requirements | Grouping phase acceptance suite |
Invariants
- Cited artifacts are not modified by C2S.
- Mutating operations append events.
- Existing events are not rewritten.
- Citation IDs are immutable.
- Handles are editable aliases.
- Replay is deterministic for the same histories, artifacts, adapters, and policy.
- Generated exports and MkDocs pages are projections, not authority.
- Unsupported or ambiguous evidence fails closed.
- Public export defaults to metadata-only.
These are falsifiable constraints. A feature that violates one is not a partial implementation of Cite2Site; it is outside the architecture until the decision record and requirements are consciously revised.
Repository Layout
.c2s/
project.json
citation-history.jsonl
handle-bindings.jsonl
artifact-index.jsonl
exports/
c2s-status.json
c2s-citations.jsonl
index-by-artifact.json
index-by-handle.json
index-by-tag.json
index-by-status.json
index-by-batch.json
site/
mkdocs.yml
docs/
index.md
citations.md
artifacts/
handles/
tags/
status/
batches/
Project File
project.json fields:
| Field | Required | Meaning |
|---|---|---|
schema_version |
Yes | Project schema version. |
repository_id |
Yes | Stable citation repository ID. |
workspace_root |
Yes | Base directory for relative artifact URIs. |
publication.privacy_mode |
Yes | Default export privacy mode. |
created_at |
Yes | Creation timestamp. |
tool |
Yes | Creating tool metadata. |
Event Envelope
Every event must include:
| Field | Required | Meaning |
|---|---|---|
schema_version |
Yes | Event schema version. |
event_type |
Yes | Event type string. |
event_id |
Yes | Hash of canonical event payload with event_id omitted. |
previous_event_hash |
Yes | Previous event hash in the same history file. |
repository_id |
Yes | Citation repository ID. |
batch_id |
When applicable | Groups related events. |
idempotency_key |
Optional | Caller-provided duplicate prevention key. |
created_at |
Yes | UTC timestamp. |
actor |
Yes | User, agent, or machine actor metadata. |
tool |
Yes | Tool name and version. |
Citation Events
citation.created
Creates a citation from accepted evidence.
Required payload:
citation_id;artifact;locator;accepted_evidence;metadata.
citation.accepted
Accepts current observed evidence as the next accepted evidence.
Required payload:
citation_id;accepted_evidence;- review metadata.
citation.retracted
Hides a citation from preferred projections.
Required payload:
citation_id;- reason.
citation.restored
Restores a retracted citation.
Required payload:
citation_id;- reason.
citation.relocated
Binds a citation to a new locator after review.
Required payload:
citation_id;- old locator;
- new locator;
- observed evidence hash.
citation.noted
Adds metadata without changing accepted evidence.
Required payload:
citation_id;- note or metadata patch.
Handle Binding Events
Event type: handle.bound.
Fields:
| Field | Required | Meaning |
|---|---|---|
citation_id |
Yes | Target immutable citation ID. |
handle |
Yes | Handle being bound, renamed, aliased, or retired. |
action |
Yes | bind, rename, alias, or retire. |
previous_handle |
For rename | Handle being replaced. |
policy.preserve_previous_as_alias |
Yes | Whether rename preserves old handle as alias. |
Rules:
- Handle collisions fail unless binding to the same citation ID.
- Rename preserves old handle as alias by default.
- Retire removes preferred display but not audit history.
Artifact Model
Artifact fields:
| Field | Required | Meaning |
|---|---|---|
adapter |
Yes | Adapter kind. |
uri |
Yes | Adapter URI. |
artifact_id |
Yes | Stable identity derived from adapter and URI/path identity. |
The artifact index should maintain:
- artifact ID;
- adapter;
- URI;
- first seen event;
- last seen event;
- citation count;
- status counts.
Adapter Contract
Status: The adapter protocol is implemented in src/c2s/adapter.py.
FilesystemTextAdapter and MarkdownAdapter pass the full conformance suite
(tests/test_adapter_conformance.py). The Markdown adapter intentionally
inherits text-line semantics; block-aware locators are deferred to a later gate.
Adapters must implement:
| Method | Behavior |
|---|---|
identify(repo, uri) |
Return stable AdapterArtifact (adapter, uri, artifact_id). |
canonicalize(repo, uri) |
Read artifact and return canonical text. |
evidence(selected_text) |
Return canonical evidence dict with content_hash, text, line_hashes, etc. |
locate(source_text, start, end) |
Return unambiguous locator with start/end/line coordinates. |
observe(repo, artifact, locator) |
Read current artifact content at locator without mutation. |
compare(accepted, observed) |
Return "resolved" or "changed"; missing/unsupported determined externally. |
summarize(locator) |
Return metadata-safe range summary. |
privacy(citation, mode, policy) |
Apply publication privacy transform to citation in-place. |
First supported adapters:
filesystem-text;markdownusing text semantics.
Commands
All commands must emit JSON on success and error.
init
Creates a dedicated citation repository.
cite-selection
Creates one citation from selected evidence.
Inputs:
- artifact URI;
- adapter;
- start/end range;
- expected content hash;
- handle;
- label;
- tags;
- note.
cite-batch
Creates multiple citations.
Rules:
- default mode:
all_or_nothing; - explicit mode:
partial; - every item has
client_item_id; - rejected items include stable codes;
- created events share
batch_id.
set-handle
Appends handle-binding event.
Actions:
bind;rename;alias;retire.
Workflow Commands
Maturity: Implemented in G5. preflight-selection is read-only and shares
the selection validator used by cite-selection. accept-current, retract,
restore, relocate, and note append citation events and require a concrete
citation ID. Replay deterministically reduces those events into current
accepted evidence, locator/artifact, state, and note metadata.
cite-selection --handle-from-first-line is an explicit parsing mode. The
first selected line must be a valid handle and must be followed by cited text;
the handle line itself is not accepted evidence.
lookup-actions
Returns contextual actions for a cursor or selection.
Overlap ordering:
- exact selection match;
- smallest containing range;
- most recent preferred-handle binding;
- citation ID lexical order.
Mutating follow-up actions must name a concrete citation_id.
citations
Maturity: Implemented in G2. The command intersects memberships from replay indexes, then emits citations in replay creation order.
Filters:
--artifact;--handle;--tag;--status;--batch;--format json|jsonl.
The query view is metadata-safe in every mode: it omits accepted evidence, observed evidence, notes, snippets, and private links. Replay and export apply the effective privacy transform before a flat projection is returned or written.
status
Replays citation state.
export
Writes JSON and MkDocs projections.
check
Validates repository integrity.
Replay Statuses
| Status | Meaning |
|---|---|
resolved |
Accepted evidence still matches observation. |
changed |
Locator resolves but evidence differs. |
missing |
Artifact or locator cannot be found. |
ambiguous |
Multiple possible observations require user choice. |
adapter_unavailable |
Adapter cannot run. |
private |
Evidence details suppressed by policy. |
unsupported |
Adapter or locator unsupported. |
retracted |
Citation hidden from preferred projections. |
Grouping And Indexing
Maturity: Done. G1 implements the deterministic in-memory indexes and the derived artifact-index cache; G2 supplies index-backed querying; G3 supplies grouped export and MkDocs projection; and G4 supplies enforced privacy transforms for flat projections.
Replay must produce flat citations plus indexes:
{
"citations": [],
"indexes": {
"by_artifact": {},
"by_handle": {},
"by_tag": {},
"by_status": {},
"by_batch": {}
}
}
Index rules:
- every active or retracted citation appears in
by_artifact; - preferred handles and aliases appear in
by_handle; - every tag appears in
by_tag; - every replay status appears in
by_status; - every batch ID appears in
by_batch; - ordering is deterministic by creation order, then citation ID;
- metadata-only mode does not include evidence text.
Publication
Maturity: Implemented. G3 writes deterministic grouped JSON indexes and MkDocs group pages with stable, collision-resistant slugs. G4 applies the effective privacy transform to flat projections, while grouped pages remain metadata-safe by contract.
Export must write:
- flat status JSON;
- flat citations JSONL;
- grouped JSON indexes;
- MkDocs index page;
- MkDocs flat citations page;
- MkDocs group pages.
Static-site publication defaults to metadata_only.
Privacy Modes
| Mode | Behavior |
|---|---|
metadata_only |
Removes accepted evidence and snippets. |
hash_only |
Emits accepted-evidence hashes and measurements, never accepted text. |
snippet |
Emits a deterministically bounded accepted-text snippet only when publication.allow_snippet is true. |
private_link |
Emits a URL derived from an authorized absolute HTTPS publication.private_link_base, with the artifact URI encoded as one path segment. |
snippet and private_link requests without their matching policy fields fail
with E_PRIVACY_POLICY. A private-link base may not contain credentials, a
query, or a fragment. Citation authority retains accepted text; projections
release it only through the explicitly authorized snippet transform.
Error Codes
Required stable errors:
E_USAGE;E_REPO_NOT_INITIALIZED;E_REPO_EXISTS;E_REPO_LOCKED;E_EVENT_CHAIN;E_EVENT_HASH;E_JSON_INVALID;E_JSONL_INVALID;E_FILE_NOT_FOUND;E_ARTIFACT_MISSING;E_ARTIFACT_TEXT_DECODE;E_ADAPTER_UNSUPPORTED;E_ARTIFACT_OUTSIDE_WORKSPACE;E_RANGE_INVALID;E_SELECTION_EMPTY;E_CONTENT_HASH_MISMATCH;E_BATCH_MODE;E_BATCH_EMPTY;E_BATCH_ITEM_INVALID;E_HANDLE_INVALID;E_HANDLE_COLLISION;E_HANDLE_ACTION_INVALID;E_CITATION_NOT_FOUND;E_PRIVACY_MODE;E_PRIVACY_POLICY;E_FIRST_LINE_HANDLE;E_HANDLE_MODE_CONFLICT;E_CITATION_RETRACTED;E_NOTE_EMPTY;E_SCHEMA_UNKNOWN;E_SCHEMA_UNSUPPORTED;E_AMBIGUOUS_CITATION_TARGET.
Validation Requirements
Every release must run:
Each new command also needs:
- success test;
- structured error test;
- source-clean test when artifacts are involved;
- deterministic output test when projection is generated.
For any architecture extension, add a counterexample test: show the forbidden behavior (source mutation, nondeterministic order, ambiguous mutation, or privacy leakage) and assert that the implementation rejects or prevents it.