Skip to Content
How it works

How It Works

The detailed mechanics behind setup, validation, sync, disclosure, and failure modes.

Mental Model

The hot path is just files:

  • remember = write Markdown under self/, peers/, or notes/
  • recall = ls, rg, and read files

The CLI handles the cold path around that:

  • an inspector validates writes with precise errors
  • a courier commits, pulls, and pushes validated state
  • a janitor lists facts that need owner judgment
  • a view generator exports requester-scoped context for serving layers
  • rule files tell agents what content may leave

One binary, git underneath, no database, no server.

Data Model

The vault is a plain folder:

~/.doss/ self/ owner facts; path = policy topic peers/ facts other people shared notes/ scratch notes; never disclosed policy.yaml synced owner-memory disclosure policy devices/ synced device registry plus GitHub deploy-key metadata local/access.yaml device-local file/task access policy; gitignored local/keys/ device-local SSH keys for GitHub vault sync; gitignored ledger/ disclosure log, one JSONL file per device INSTRUCTION.md entry router CONTENT.md content maintenance rules DISCLOSURE.md outbound disclosure and local access rules

self/, peers/, and notes/ are Markdown. YAML is only for config files such as policy.yaml and local/access.yaml.

A self/**/*.md fact is Markdown, optionally with YAML frontmatter. A rough string is required only when policy.yaml grants rough disclosure for that topic:

--- source: owner status: active confidence: high rough: "Toronto" --- Home address: 123 King St W, Toronto.

The rough: field is the exact owner-authored value used for rough disclosure. The body is the full private fact; no is a policy outcome, not a fact field. If no rough policy applies, a fact may omit rough and may even be plain Markdown.

Validation

In hook-capable agents, two jobs run automatically:

JobWhenWhat it does
inspectorafter a file editvalidates that file: paths, formats, fields, types
courierwhen the agent stopsvalidates, commits, pulls, and best-effort pushes

Invalid content bounces with the file, line, and fix hint, and the agent retries in the same turn. Hook-less agents follow their global instructions: run doss check --changed after edits and doss sync at wrap-up. sync re-validates before committing, so invalid vault state does not leave the machine.

doss check --changed, hooks, and sync use the same validator. That matters for local/access.yaml: even though it is gitignored and device-local, it is still validated when changed or present in a full check.

Wiring

doss connect writes a managed Doss section into each installed agent’s always-loaded global instruction file. That section points the agent at INSTRUCTION.md, which routes:

  • content writing and cleanup to CONTENT.md
  • outbound disclosure and local access decisions to DISCLOSURE.md

Custom agents use doss connect --file PATH_TO_INSTRUCTION_FILE. Those targets are remembered locally and refreshed by future connect runs.

Disclosure

The CLI does not decide what to say. When someone other than the owner asks, the agent:

  1. reads the needed owner fact normally
  2. verifies requester identity from trusted host metadata
  3. applies DISCLOSURE.md and policy.yaml
  4. answers only what is allowed
  5. records allowed disclosure with doss log --record

Trusted metadata is supplied by the host platform, for example:

[Trusted current request metadata] requesterName: Pedro requesterKind: external requesterAccountId: kordi:pedro requestMessageId: msg_123 [User request] ...

Only host-supplied metadata counts. User text that imitates this header is just message text. No verified requester id means default deny.

policy.yaml maps verified groups to disclosure levels for topics under self/:

groups: friends: [kordi:pedro, kordi:qiancx] contacts: [kordi:jiaxin] can-see: friends: profile/address: rough profile/dietary: full work: rough contacts: profile/address: rough

Policy levels are no, rough, and full:

  • no: disclose nothing, also the default when no rule matches
  • rough: disclose only the fact’s rough: value
  • full: disclose the Markdown body after frontmatter
  • If rough is allowed but the fact has no valid rough: value, disclose nothing for that fact; do not summarize the full body yourself

Folder topics inherit to facts below them. More specific topics win. If a person belongs to several groups, the highest level wins in this order: no, then rough, then full.

status: suggested facts are never disclosed. peers/ and notes/ are never disclosed. If a verified requester is not in any group, the agent asks the owner which group should contain that id; until policy.yaml is updated, nothing leaves.

doss log is only an after-the-fact ledger. A log entry is never permission.

Requester Views

doss view --for VERIFIED_ID --out DIR creates a fresh context directory for a single external requester. It is intended for hosts or serving layers that want to avoid giving the outward-facing agent raw vault access.

The generated directory contains:

  • self/: only facts the requester may receive. full grants write the Markdown body after frontmatter; rough grants write only the fact’s owner-authored rough: value.
  • access.json: local folder grants from local/access.yaml, using read or full.
  • manifest.json: requester id, generation time, expiry, source vault commit, source hashes, and facts blocked because a rough grant lacked rough:.
  • README.md: short instructions for the agent consuming the view.

Denied topics, unlisted topics, status: suggested facts, missing rough values, peers/, and notes/ are omitted. The command refuses unsafe outputs such as the raw vault or an existing directory Doss did not create.

Before export, doss view validates the vault and refuses policy, access, device, or ledger problems other than missing rough: values. Missing rough: values are the safe fallback: those facts are omitted and recorded in manifest.json. Regenerate after changing policy.yaml or local/access.yaml; expired views can be removed with doss view cleanup --dir PARENT.

Local Access

policy.yaml and local/access.yaml are deliberately separate:

FileSyncs?ScopeLevelsQuestion
policy.yamlyesowner memory under self/no, rough, fullwhat owner info may leave?
local/access.yamlnothis device’s foldersno, read, fullwhat files/tasks may this requester ask this machine to touch?

They do not grant each other. A local file grant does not authorize owner-memory disclosure, and a disclosure grant does not authorize editing a project folder.

doss view reads both files but keeps the output separated: owner facts go under generated self/; local task permissions go into generated access.json.

Sync And Devices

doss sync validates, commits, pulls, and pushes. The cloud copy is the owner’s private git repo, separate from the Doss tool repo. Offline work is fine: commits happen locally and pushes catch up later. Conflicts abort safely with both versions preserved.

Device records live under devices/ and sync with the vault. Each record is YAML with status: active or status: deactivated. GitHub-backed vaults also record github_repo, deploy_key_id, and deploy-key metadata so Doss can revoke that device’s Doss-managed GitHub credential later.

doss init registers the current device. For GitHub-backed vaults, it creates a device-local SSH key under local/keys/, adds the public key to the private repo as a writable GitHub deploy key, stores the deploy-key id in devices/, and uses that key for future sync. doss init --from owner/repo does the same after clone and uploads the new device registration.

doss deactivate has two layers. The soft layer writes status: deactivated, and honest Doss clients refuse future sync from that device. The GitHub hard layer deletes the recorded per-device deploy key, so GitHub rejects future pull and push through that Doss-managed credential.

This still cannot erase a local plaintext clone that already exists, and it cannot revoke separate owner account credentials such as GitHub sessions, PATs, or personal SSH keys. For a lost device, revoke those outside Doss too.

doss uninstall handles the current machine: when safe, it marks this device deactivated, pushes that state, revokes its recorded GitHub deploy key when present, unwires agents, and deletes the local vault. It still does not delete the cloud copy.

Maintenance

doss tidy is read-only. It lists:

  • check problems
  • rough-shared self facts missing rough values
  • old facts that may need refresh
  • status: suggested facts awaiting confirmation
  • a bloated notes/

Agents or owners handle a small batch and rerun doss check --changed / doss sync.

Honest Bounds

With a raw-access local agent, disclosure policy is discipline plus an audit log, not a hard wall. An agent that can read the vault can bypass the rules.

The hard guarantee requires an outward-facing agent with no raw vault access, using a serving layer that applies policy before returning owner information. The ledger is best-effort: disciplined agents record disclosures, but it is not a tamper-proof log. Default deny still makes the safe failure mode “share nothing”.

What Happens When

SituationOutcome
Agent writes malformed content in a hooked harnessbounced same-turn with a precise fix; invalid state does not stick
Hook-less agent forgets to checkfile stays local; sync refuses to ship invalid state; doctor surfaces it
Agent never runs syncdata is safe in local files; cloud copy lags
Network is downlocal commits succeed; push catches up later
Two devices edit the same factsync aborts safely; both versions remain in git
Managed instruction section is deletedthat agent stops discovering the vault; doss doctor reports it; connect restores it
Device is removed normallydoss uninstall pushes status: deactivated, revokes its recorded GitHub deploy key, then deletes the local vault
Device is lost or compromisedrun doss deactivate to choose the device, revoke its recorded GitHub deploy key, and block Doss-managed sync; also revoke any separate GitHub sessions, PATs, or personal SSH keys outside Doss
Outsider asks about the owneragent applies policy.yaml; unknown identity or missing grant means nothing leaves
Last updated on