Skip to content

Landing and why notes

wayglass land takes an approved change to the trunk:

  1. The Worker checks that the intent’s latest decision is approved, that the fork head is still the commit that was decided, that a stacked intent’s parent has landed, and that no other land is in progress for the project. Then it mints a trunk write token valid for 300 seconds and records the trunk head at that moment.
  2. The CLI fetches the trunk. If the trunk head is no longer what the Worker recorded, it stops with trunk_moved and pushes nothing; run land again.
  3. If the approved commit already contains the trunk head, it lands as a fast-forward. Otherwise the CLI merges it onto the trunk in a temporary worktree (see below).
  4. It pushes the result to the trunk, writes the why note on the landed commit (and on the approved commit, if a merge was needed), and pushes refs/notes/wayglass.
  5. The Worker revokes the trunk token and verifies that the trunk now holds exactly the approved change: the approved commit itself, or a merge of it that touches only the decided paths. A mismatch is recorded in the audit log as land.mismatch.
  6. If .wayglass/config.yaml sets mirror (a git remote name such as origin), the CLI pushes the trunk branch and notes there, with your own git credentials, never an Artifacts token. --no-mirror skips this.
  7. The local branch is fast-forwarded to the landed commit when that loses nothing (clean checkout, no divergence).

Until the Worker has verified the trunk, any failure hands the land back at once (land/abort): the trunk token is revoked and the next agent can land without waiting for it to expire.

When other changes landed after the intent forked, land merges the approved commit onto the newer trunk with git merge --no-ff. It never rebases, so the commit that lands is the one policy classified and someone approved.

  • Edits that git merges cleanly in the decided files land. JSON output lists them under merged_paths and sets trunk_moved: true.
  • A conflict stops with land_conflict. Nothing is pushed. Merge the trunk into the intent, resolve, push and propose again.
  • A merge that would bring in changes to files the decision did not cover stops with repropose_required. Nothing is pushed. Merge the trunk into the intent, push and propose again, so the new file set gets its own decision.

The user’s checkout and branches are not touched by the merge; it happens in a throwaway worktree.

The why lives in git, under refs/notes/wayglass, attached to the landed commit. The note body is JSON:

Field Meaning
v Note format version
intent_id, goal, reason The intent, as declared
tags Area, data class, risk and jurisdiction, with evidence
rule, action The rule that matched and the action it chose
decision_id, status The Worker’s decision record
decided_by, decided_at policy for automatic decisions, otherwise the approver
approvals Each verdict with its author, reason and time

wayglass why <file>:<line> blames the line to its commit and reads that note. If the checkout has no note for the commit, it asks the Worker, which keeps the same record. Notes are pushed to the mirror as well, so anyone with a clone can run git fetch origin refs/notes/wayglass:refs/notes/wayglass and read them.

Notes survive an Artifacts fork, so a forked session also carries the why of everything that landed before it.

Separately from the notes, the Worker keeps an append-only audit log per project: intents declared and pushed, overlaps, decisions with their rule and reason, approvals with theirs, land tokens issued, lands, aborts and mismatches, and trunk pushes reported by Artifacts events. Read it with wayglass log:

Terminal window
wayglass log --limit 20
wayglass log --intent i5e39df9bcd --json
wayglass log --kind decision