Use Weave

Decisions & history

Decision records, the operation log, timeline, blame and symbol history, revert and undo, tags and attestations.

View as Markdown

Every change in Weave carries what it was for and why. History only moves forward: revert and undo add new entries, nothing is rewritten.

Decision records#

A decision record says why code is the way it is: a title (≤ 80 characters), the why (≤ 240), rejected alternatives and constraints, anchored to symbols. Records are files, .weave/decisions/D-xxxx.toml, that travel draft → stitch → weaved with the code, so they are owned, promoted, inherited and reverted like the code they explain. Agents need .weave/decisions/** in their pathScope to stitch them.

Record decisions#

bash
# at stitch time: -w drafts a record anchored to the symbols you changed (confirm it, or -y)
weave stitch -i "Keep bcrypt" -w "login p99 budget is 250ms" -y

# directly
weave decision add -t "Keep bcrypt cost at 12" -w "login p99 budget is 250ms" \
  --on src/auth.rs::hash_password --alt "argon2id" --constraint "p99 login < 250ms" --comment

--comment puts a one-line why: … [D-xxxx] comment above each anchor. That tag is the strongest anchor: the record follows it through moves and renames. WEAVE_DECISION_YES=1 records drafted decisions without asking.

Read decisions (within a token budget)#

bash
weave decision for src/auth.rs::login                   # one short line per decision on it and its neighbours
weave decision for src/auth.rs::login --format constraints
weave decision search "password hashing" --near src/auth.rs::login
weave decision impact src/auth.rs::login --depth 2      # callers and callees with their decision counts
weave decision show D-7f3a
weave decision list --all                               # or --status active|needs_review|superseded|stale|retired

--format constraints prints rules for an agent's starter pack, best decision first:

KEEP: Keep bcrypt cost at 12 — login p99 budget is 250ms [D-7f3a]
KEEP: p99 login < 250ms [D-7f3a]
NEVER: argon2id [D-7f3a]

Keep decisions current#

When an anchored symbol changes, its decisions become needs_review; when every anchor is lost, stale.

bash
weave decision review                 # follow moved / renamed anchors, mark drift, list the queue (--dry-run)
weave decision review D-7f3a --accept # it still holds
weave decision supersede D-7f3a -t "Use argon2id" -w "new hardware budget"
weave decision retire D-7f3a --reason "auth moved to the identity service"

weave enrich can find unconfirmed why-candidates with an LLM (your key, on your machine); weave decision review --candidates lists them and weave decision confirm <n> turns one into a decision.

MCP: decisions_for, decision_search, decision_get, impact, decision_propose, decision_review. Server API: GET|POST /api/weave/{repoId}/decisions, GET …/decisions/{id}, POST …/decisions/{id}/supersede, POST …/decisions/{id}/retire, POST …/decisions/review (see API reference). Server writes are stitches too, so a write to a record someone else owns becomes a suggestion.

Threads#

Threads are the lighter companion: short behaviour notes per symbol, written directly to sidecars under .weave/threads/ without drafts or stitches.

bash
weave thread add src/auth.rs::login "token refresh is lazy"
weave thread show login --depth 1
weave thread search "refresh"
weave index && weave thread heal      # after renames

Timeline and the operation log#

bash
weave timeline                         # weaved stitches of the active workstream, newest first
weave timeline main --limit 20         # author, agent, intent, why, promoted / inherited / revert
weave log                              # the operation log: every action, newest first (default 30)
weave log --actor alice --workstream main --limit 50
weave log --by-agent builder-1
weave log --symbol src/auth.rs::login  # everything that touched a symbol
weave log --verify                     # check the log's hash chain first

The operation log records every action — claims, releases, lease expiries, stitches, weaves, rejections, suggestions, change requests, promotions, reverts, undos, workstream removals, tags, attestations, purges — with the person and agent. It is append-only and hash-chained: each entry's id is the BLAKE3 hash of its content and the previous entry's id. In the web UI it is the repository's Log tab, with filters for person, agent, workstream and symbol.

Blame and symbol history#

Which weave last changed each symbol of a file (server API, read access):

bash
curl -s "https://api.weave.directory/api/weave/$REPO_ID/workstreams/main/blame?path=src/auth.rs" \
  -H "Authorization: Bearer $WEAVE_TOKEN"
json
{ "type": "blame", "workstream": "main", "path": "src/auth.rs", "head": "…", "total": 3, "next_offset": null,
  "items": [{ "symbol": "src/auth.rs::login", "kind": "function", "changeset": "…", "label": "stitch",
    "author": "alice", "agent": null, "at": "…", "intent": "MFA login", "why": "SOC2", "entry_id": "…" }] }
  • Paged with offset and limit (default 200, max 1000). A symbol unchanged since its workstream was created is attributed in the parent.
  • GET …/workstreams/{ws}/symbol-history?symbol=src/auth.rs::login lists every weave that changed one symbol.
  • GET …/workstreams/{ws}/history pages weaved stitches newest first (before, limit ≤ 500) and filters by kind, agent, author, source and symbol. Items carry reverted_by / reverts links.
  • GET /api/weave/{repoId}/diff?from=<head|workstream>&to=<head|workstream>&level=file|symbol&path= diffs two heads, by file or by symbol.

Revert and undo#

bash
weave revert 9c1e --why "broke MFA on mobile"   # a new stitch with the inverse operations
weave undo                                      # reverse your own most recent action
weave undo <log entry id prefix>                # or a chosen entry of yours
  • Revert takes back a weaved stitch with a new stitch. Symbols unchanged since are reverted; a symbol changed again since is not overwritten but becomes a change request. --why is required.
  • Undo reverses your own action: a weaved stitch is reverted, a claim released, a suggestion withdrawn, a rejection reopened, a settings change restored, a removed workstream restored. Someone else's action is taken back with a revert or a suggestion instead. Undo is logged and never deletes entries.
  • Several stitches as one revert, all or nothing (server API): POST /api/weave/{repoId}/workstreams/{ws}/revert with {"changesets": ["<id>", "<id>"], "why": "…"}. If a later weave changed one of the symbols, it answers 409 revert_conflict with the blocking symbols and nothing is weaved.
  • Restore paths or symbols to an older head as a new stitch: POST /api/weave/{repoId}/restore with {"workstream", "head", "paths"?, "symbols"?, "intent"?, "why"?}.
  • Web UI: Weaved → Revert on a stitch; Log → undo on your own entries.

Tags#

Tags are immutable names for heads (server API):

bash
curl -s https://api.weave.directory/api/weave/$REPO_ID/tags \
  -H "Authorization: Bearer $WEAVE_TOKEN" -H "Content-Type: application/json" \
  -d '{"name": "v1.2.0", "workstream": "main", "message": "spring release"}'
  • workstream alone tags its current head; or pass head (a state of the repository). Write access.
  • Names: letters, digits, ., _, -, /, ≤ 128 characters, no leading - . /, no trailing /, no .. or //.
  • The same name for the same head answers 200 created: false; for another head, 409.
  • GET …/tags[?head=] lists them newest first; GET …/tags/{name} (encode / as %2F); DELETE …/tags/{name}?why= (repository admin).
  • Tags aren't accepted as refs by diff, archive or restore yet: pass the tag's head.

Attestations#

An attestation is a signed statement about one exact head — tests passed, security reviewed, approved — that a protected workstream can require before a promotion.

  1. Register a key (Ed25519). Repository keys: POST /api/weave/{repoId}/attestation-keys {"publicKey": "<base64 of the raw 32-byte key>", "label"?, "types"?: ["approval"]} (repository admin). Organization keys, trusted in every repository of the org: POST https://weave.directory/api/v1/orgs/{slug}/attestation-keys (scope org:admin). A key's id is wak_ + the first 32 hex of sha256(raw public key).

  2. Sign this text (UTF-8, \n between lines, no trailing newline):

    text
    weave-attestation/v1
    repo:<repo id>
    head:<head, 64 lowercase hex>
    type:<type>
    payload-sha256:<lowercase hex sha256 of the canonical payload bytes>
    

    A string payload is its UTF-8 text as is. Any other JSON is compact, with object keys sorted, recursively.

    js
    import crypto from "node:crypto";
    const canonical = (v) => typeof v === "string" ? v
      : Array.isArray(v) ? `[${v.map(canonical).join(",")}]`
      : v && typeof v === "object" ? `{${Object.keys(v).sort().map((k) => `${JSON.stringify(k)}:${canonical(v[k])}`).join(",")}}`
      : JSON.stringify(v);
    function attest(privateKey, repo, head, type, payload) {
      const text = typeof payload === "string" ? payload : canonical(payload);
      const digest = crypto.createHash("sha256").update(text, "utf8").digest("hex");
      const msg = `weave-attestation/v1\nrepo:${repo}\nhead:${head}\ntype:${type}\npayload-sha256:${digest}`;
      return crypto.sign(null, Buffer.from(msg, "utf8"), privateKey).toString("base64");
    }
    
  3. Post it: POST /api/weave/{repoId}/heads/{head}/attestations {"type", "payload", "signature", "keyId"} (write access; any principal). head must be a 64-hex state id, so you attest exactly what was checked. The signature is verified on the way in.

  4. Read them: GET …/heads/{head}/attestations (a workstream name works here). Anyone can fetch a public key without a token: GET /api/weave/attestation-keys/{keyId}.

A revoked key verifies no attestation recorded after its revocation; ones it signed before stay valid.

Verified audit trail#

The server verifies every repository's hash-chained log every hour and writes checkpoints to write-once storage, chained to each other. Read the latest with GET /api/weave/{repoId}/audit/verification (read access; ?deep=true for admins re-checks the stored checkpoint) and export the log with GET …/audit/export?from=&to=&format=json|ndjson (admin). GET …/log/verify checks the chain on demand. See Security & access.