# Project orchestration

Run these commands from the parent workspace of a project with versioned
[repository mounts](/docs/repository-mounts.md). The current workspace view selects
participating children. Each repository retains its own history, permissions,
locks, and durable operation outcomes. Acceptance is atomic **per repository**.

For a worked example, start with [daily work with a game, engine, and optional
art repository](/docs/tutorials/work-with-mounts.md). It covers an ordinary game-file
edit, a coordinated engine/game change, adopting a dependency revision, selecting
art sources, and recovering an interrupted publication.

`scribe project` adds coordination across workspaces. Ordinary `scribe edit` and
`scribe submit` already work on parent files such as `game/src/foo.cpp`, and remain
sufficient when only that repository changes. Inside a mounted directory, those
same ordinary commands address the child repository. `project publish` automates
the child submission, parent pin edit, and parent submission that you can also
perform separately.

```sh
scribe project status --scan --remote
scribe project sync
scribe project publish -m "Update the engine and game together"
```

## Inspect the assembled project

`project status` works offline. It reads the working-copy `.scribe/config.toml`
and reports the parent, declared children, and retained directories whose mounts
were removed. For each initialized component it shows the declared pin, completed
sync watermark, accepted local submission since that sync, opened paths,
conflicts, deferred updates, view changes, moves, and pending submissions. An
unfinished publication includes its ID and each participant's phase and operation
ID. Missing components are reported individually; they do not hide other status.

By default, path inspection covers opened work. `--scan` adds tracked and untracked
discovery; `--verify` implies scanning and hashes bytes. `--remote` checks selected
components with their own authorization and adds branch heads and live lock
information. Excluded children are never probed remotely, even if a retained local
copy exists. A remote head is informational; it does not change a pin. Connection
failures still return local component status with a nonzero inspection exit status.

The sync watermark and local submission revision are deliberately separate:
submitting opened files does not mean all other files have been synced to that
revision. A subsequent completed sync clears the local submission receipt. An
explicit historical child sync also reconciles submitted files back to that
revision, retaining displaced bytes through the ordinary recovery machinery.

## Sync a fixed composition

`project sync [--revision N]` uses the same implementation as `scribe sync`.
It reads the parent configuration at the exact selected parent revision, resolves
metadata for every selected child before applying files, then applies the parent
and each child through their workspace journals. It never follows a child head.

An inaccessible selected child makes the overall result incomplete. Accessible
components can finish. Once all parent file operations finish, the parent's own
watermark advances and its file journal closes, so an inaccessible child does not
block unrelated parent work. The composition remains incomplete: a separate
mount-sync marker retains the target for retry, and each unfinished child keeps
its own journal. Rerunning resumes the recorded target and reports the mixed
state. Unselected mounts need no target requests or transfers. Local work,
changed component identities, unsupported recursive mounts, and independent
submitted child revisions retain their existing protection rules.

## Stage a pin explicitly

After independently submitting or syncing a child to the desired revision:

```sh
scribe project update engine
# Or select an exact accepted revision explicitly:
scribe project update engine --revision 42
scribe status
# Review .scribe/config.toml in your editor before submitting.
scribe submit -m "Use engine revision 42"
```

The positional argument is the mount **name**, which can differ from its path.
Without `--revision`, the target is the child's local sync/submission revision;
it never means the remote head. An explicit target can be staged without a local
child checkout, but the caller must be able to read that target. Invalid or
recursive targets are refused.

This command only opens and edits the parent's tracked configuration, using its
normal lock policy. It replaces revision values while preserving comments,
profiles, lock rules, and other TOML formatting. The file must be in the view.
Finish existing sync, view, move, submit, branch, and conflict workflows first.
Stage independent child updates before starting a parent sync against an older
pin. A parent already waiting on that old pin retains its target: explicitly sync
the child to the recorded pin (its newer history remains accepted), or change the
selection using the mount-only recovery described in the mount guide.

## Publish children, then the parent

Open intended changes using normal `edit`, `add`, and `delete` commands in each
workspace. Publication includes opened changes in selected children plus opened
parent changes. Unopened edits and untracked files are not implicitly added.
Finish merges/conflicts and other active workflows before starting. A child merge
or cherry-pick must be accepted with an ordinary child `scribe submit` first;
project publication then adopts that accepted revision without resubmitting it.

`project publish -m MESSAGE`:

1. Checks all selected workspace identities, local workflow state, target metadata,
   and upload authorization; opens the parent configuration under its lock policy.
2. Persists a root publication journal containing participant identities and one
   operation ID per repository workspace, then freezes and uploads all candidates
   before transmitting any submission.
3. Submits children in mount-name order. Each accepted child revision is recorded.
4. Stages the parent pins to those confirmed revisions, preserves the previous
   config in `.scribe/_state/recovery`, and submits the frozen parent candidate. Other
   parent files retain the bytes prepared in step 2.
5. Clears participant ownership and the root journal after recording completion.

All selected local workspaces must exist and be available. Clean children keep
their local revision; already independently submitted children need no duplicate
commit. Excluded mounts retain their declared pins. A parent operation is needed
only when opened parent/child work or a changed local child revision requires it.
No additional versioned manifest or lockfile is created: composition stays in
`.scribe/config.toml`, and execution state stays inside `.scribe/_state/`.

## Resume or abort

```sh
scribe project status --scan
scribe project publish --continue
scribe project publish --abort
```

A transport failure leaves the publication pending. `--continue` resolves each
persisted operation outcome and, only when no result exists, retransmits that
same candidate and operation ID. A child accepted before a lost reply—or before
the root recorded its receipt—is not submitted again. A lost parent reply is
resolved independently. Normal workspace mutations are blocked while the project
owns a workspace; ordinary `status` points back to the root recovery commands.
Keep all participating directories in place while recovering.

If a parent submission is rejected after a child succeeds, the child remains
accepted. Abort the publication, resolve the parent's rejection, review the
staged pin, and publish again. A recorded rejection is never retried as different
intent under the same operation ID.

Abort removes unsent candidates and releases project ownership while preserving
opened work, staged configuration changes, and accepted history. Every transmitted
operation must first have a confirmed outcome. If its outcome is still unknown,
abort refuses; use `--continue` with restored connectivity/access first. After a
repository restore, an absent outcome in a new authoritative incarnation retires
and archives the old intent, following ordinary submit recovery. Abort
never rolls back a child commit. The CLI reports incomplete publication with a
nonzero exit status and lists each participant's result.

Edits made after preparation remain on disk; they are not silently incorporated
into retries. If the configuration itself changes before the planned pin update,
publication pauses and preserves it. Preserve those edits and restore the planned
configuration to continue, or abort and start a new publication after review.

## Web and SDK

The web interface shows the accepted parent pins and links to the independently
authorized child revisions. Its mount editor explains the same child-first
workflow: submit child changes, then commit the parent pin. It does not report
local workspace progress, which lives only in the user's `.scribe/_state/` journals.
After CLI publication, the existing parent history, mount cards, and child
click-throughs show the newly accepted composition.

The TypeScript SDK's existing mount reads and per-repository submit/outcome APIs
continue to describe accepted server state. No new wire or HTTP operation is
needed for this local orchestration layer, and no parent permission authorizes a
child operation.
