Use Weave

Workstreams

The main ← preprod ← dev chain, promote and inherit, ownership and inherit settings, protected workstreams, removing and restoring.

View as Markdown

A workstream is a line of work: main, preprod, dev, feature/auth. Everyone on a workstream shares its head. Every workstream except main has a parent, and together they form a chain. Weaved stitches move up the chain by promotion and down by inheritance.

main        weaved = deployable to production
 └─ preprod weaved = deployable to staging
     └─ dev weaved = the team's integrated work

Names#

A workstream name is one or more parts separated by /: main, feature/auth, dev/section-of-system. Parts use letters, digits, -, _ and .; no empty, . or .. parts; at most 100 characters. weave workstream new lower-cases the name and turns spaces into -. In a URL path a name is one segment, so encode / as %2F (/workstreams/feature%2Fauth/head).

Create a workstream#

bash
weave workstream new feature/auth --from dev            # creates it and switches to it
weave workstream new sandbox --from main --ownership workstream --inherit manual
weave workstream list                                   # parent, head, ownership, inherit, weaved count
weave checkout dev                                      # switch the files on disk to another workstream

--from (alias --base) defaults to the active workstream. Over the server API:

bash
curl -s https://api.weave.directory/api/weave/$REPO_ID/workstreams \
  -H "Authorization: Bearer $WEAVE_TOKEN" -H "Content-Type: application/json" \
  -d '{"slug": "feature/auth", "parent": "dev", "settings": {"ownership": "repo", "inherit": "auto"}}'
json
{ "type": "workstream", "workstream": {
    "slug": "feature/auth", "parent": "dev", "parent_head": "…", "synced_parent_head": "…", "head": "…",
    "settings": { "ownership": "repo", "inherit": "auto" },
    "created_by": "<userId>", "created_at": "2026-10-30T12:00:00Z", "archived_at": null, "archived_by": null } }

An existing name answers 409 conflict. A removed (archived) workstream keeps its name: restore it instead. In the web UI: the repository's Workstreams tab → New workstream, pick Created from, click Create.

Parents can't change later#

There is no call to change a workstream's parent. Create the chain in order, top down.

Set up main ← preprod ← dev#

  1. Create the repository with only preprod (so it doesn't create the default dev under main):

    bash
    curl -s https://weave.directory/api/v1/orgs/acme/repos \
      -H "Authorization: Bearer $WEAVE_PAT" -H "Content-Type: application/json" \
      -d '{"name": "shop", "workstreams": ["preprod"]}'
    

    This gives main and preprod (parent main).

  2. Create dev under preprod, in a checkout or over the API:

    bash
    weave workstream new dev --from preprod
    # or
    curl -s https://api.weave.directory/api/weave/$REPO_ID/workstreams \
      -H "Authorization: Bearer $WEAVE_TOKEN" -H "Content-Type: application/json" \
      -d '{"slug": "dev", "parent": "preprod"}'
    
  3. Check: weave workstream list (or GET /api/weave/{repoId}/workstreams) should show dev → preprod → main.

Seeding from a template? Seed main first, then create preprod and dev, so they start from the seeded head (see For AI agents).

Promote: move a stitch up#

bash
weave timeline                         # weaved stitches of the active workstream, with ids
weave promote 9c1e --to preprod        # a stitch id prefix
weave promote 9c1e --to preprod --with-deps
weave status                           # per stitch: promotes cleanly / needs <stitch> / clashes on <symbol>
  • Promotion submits the stitch to the target's own weave check and keeps its author, agent, intent and why.
  • If it relies on earlier stitches that aren't in the target yet, Weave lists them and asks; --with-deps promotes them together. With --json and without --with-deps you get the error code needs_dependencies with the list.
  • A symbol that changed differently in the target opens a change request there instead of weaving.
  • Between two workstreams with ownership: repo, ownership is not checked again.

API: POST /api/weave/{repoId}/workstreams/{from}/promote with {"to": "preprod", "changesets": ["<id>"], "with_dependencies": false}. In the web UI, the Weaved tab has Promote to {parent} on each stitch.

Inherit: receive the parent's weaves#

When the parent weaves a stitch, each child receives it according to its inherit setting:

inheritWhat happens
auto (default)The child receives the stitch at once, for every symbol it hasn't changed itself.
manualNothing until you run weave refresh (or the Inherit from parent button), which inherits each pending parent stitch in order.

Symbols the child changed differently get a change request as soon as the clash exists — you know early, not at promotion time.

Change requests between workstreams#

A change request shows the base version and both sides, each with author, agent, intent and why. Nobody merges lines.

bash
weave cr list                          # open change requests in this workstream (--all for resolved)
weave cr show <id>                     # both sides
weave integrate <id|workstream>        # private integration draft: clean symbols applied, clashes listed
weave cr resolve <id> this             # keep this workstream's version
weave cr resolve <id> other            # take the incoming version
weave cr resolve <id> edit             # take the symbol as edited on disk (or --text / --from-file)
weave stitch -i "Take dev's token refresh"   # build, test, then weave the resolution

The integration draft is private until you stitch it, so nobody sees a half-resolved state.

Settings: ownership and inherit#

SettingValuesMeaning
ownershiprepo (default)One owner per symbol across every repo workstream. Approval happens once; promotion between such workstreams never re-asks.
workstreamThe workstream has its own owners (an experimental sandbox). Promoting from it can raise change requests for the target's owners.
inheritauto (default) / manualSee above.

Change them later:

bash
curl -s -X PATCH https://api.weave.directory/api/weave/$REPO_ID/workstreams/dev/settings \
  -H "Authorization: Bearer $WEAVE_TOKEN" -H "Content-Type: application/json" \
  -d '{"inherit": "manual"}'

Only a repository admin, or the creator of a non-main workstream (with write access), may change settings. Changing ownership while someone else holds a live claim in the workstream's scope is refused with 409, unless an admin sends "force": true. In the web UI: the workstream's page → Settings → Save settings.

Protected workstreams#

A protected workstream only changes by promotion (and inheritance from its parent). Direct stitches, web edits, restores, accepted suggestions, change-request resolutions and reverts are refused for everyone but repository admins (403 "workstream main is protected: changes arrive by promotion only").

You can also require attestations — signed statements such as tests, security or approval — on the source head before a promotion is let in:

bash
# repo admin
curl -s -X PUT https://api.weave.directory/api/weave/$REPO_ID/workstreams/main/protection \
  -H "Authorization: Bearer $WEAVE_TOKEN" -H "Content-Type: application/json" \
  -d '{"requireAttestations": ["tests", "approval"]}'

# preflight: is preprod's head ready to promote into main?
curl -s "https://api.weave.directory/api/weave/$REPO_ID/workstreams/main/protection/check?head=preprod" \
  -H "Authorization: Bearer $WEAVE_TOKEN"

A promotion without them answers 409 attestations_required with required, missing and invalid. Admins are not exempt: to release without attestations an admin removes the protection (DELETE …/protection), which is logged. How to sign an attestation: Decisions & history.

Remove and restore a workstream#

Removing a workstream archives it: it is hidden from lists, read-only, and its history and head stay readable by name (weave cat --workstream, weave timeline). Nothing is deleted.

bash
weave workstream remove feature/auth            # alias: archive
weave workstream remove feature/auth --force    # even with weaved stitches not promoted to the parent
weave workstream list --archived                # removed ones too, "(removed <date> by <user>)"
weave workstream restore feature/auth
  • Refused for main (400), for the active workstream (switch first), while it has child workstreams that aren't removed (409, listed), and while weaved stitches aren't promoted to its parent unless --force (409 unpromoted_stitches, with the count).
  • Only its creator or a repository admin may remove or restore it. Path-scoped and verifier agents never may.
  • On removal, open change requests are closed (keeping its own side), pending suggestions are rejected, claims in its own ownership scope are released and open resolution points are closed. Restoring does not reopen them; weave refresh catches it up with its parent.
  • weave undo of a removal restores it. A restore is refused while the parent is removed.

API: platform DELETE /api/v1/repos/{repoId}/workstreams/{ws}?force=true|false and POST /api/v1/repos/{repoId}/workstreams/{ws}/restore (personal tokens and worker agent tokens with repo:write), or the server routes DELETE /api/weave/{repoId}/workstreams/{ws}?force= and POST …/restore. Web UI: Workstreams → Remove workstream (tick Remove it anyway. when asked), and Show archived → Restore.

Hibernate: park your draft#

bash
weave hibernate          # park your draft in this workstream; files on disk show the weaved head
weave checkout main      # look at something else
weave checkout feature/auth && weave resume   # bring the draft back, carried onto the current head

weave checkout refuses while files on disk have edits you haven't added.