Redesign spine tasks to align better with OpenSpec #20

Closed
opened 2026-09-14 09:13:47 -04:00 by cmoriarty · 1 comment
Owner

I would like to iterate on the naming of the steps on the spine, to better align them with OpenSpec and Git Feature Branching. Script tasks should be prefixed with "script", openspec tasks should be prefixed with "openspec", git tasks should be prefixed with "git", "human" for tasks requiring a human, and we should follow this pattern to make the naming more representative of their action. I'd like to see clearly all of the openspec steps - explore, propose, apply.

Also we should build in the functionality that the user could merge the PR from braid, as well as archive the change. Both of those should be human gates that present a dialog. I will likely merge the PR from Frogejo, so the system should be able to handle the case where the gate is stopped waiting, the user merges the PR, comes back to braid and is able to "re-check" the pull request to see if it has been merged already.

Here's a snapshot of the current spine task listimage

For example: I assume "workspace.prepare" does some work, but all that ends up in the agent console is "wrote .osf/brief.json for run_01M2FZ72MEAJZV8QPNN0EB9VCD". What is this step actually doing? A better name, and if something else is happening, it should be clear in the agent console. When does the repo get cloned? when does the branch get made?

Also I noticed the review and revise labels were white before the run got to those steps.

I would like to iterate on the naming of the steps on the spine, to better align them with OpenSpec and Git Feature Branching. Script tasks should be prefixed with "script", openspec tasks should be prefixed with "openspec", git tasks should be prefixed with "git", "human" for tasks requiring a human, and we should follow this pattern to make the naming more representative of their action. I'd like to see clearly all of the openspec steps - explore, propose, apply. Also we should build in the functionality that the user could merge the PR from braid, as well as archive the change. Both of those should be human gates that present a dialog. I will likely merge the PR from Frogejo, so the system should be able to handle the case where the gate is stopped waiting, the user merges the PR, comes back to braid and is able to "re-check" the pull request to see if it has been merged already. Here's a snapshot of the current spine task list![image](/attachments/49c70ecc-bd9c-4286-8eb1-bb1de530da1f) For example: I assume "workspace.prepare" does some work, but all that ends up in the agent console is "wrote .osf/brief.json for run_01M2FZ72MEAJZV8QPNN0EB9VCD". What is this step actually doing? A better name, and if something else is happening, it should be clear in the agent console. When does the repo get cloned? when does the branch get made? Also I noticed the review and revise labels were white before the run got to those steps.
175 KiB
Author
Owner

Shipped in 01c21ed, and archived as 2026-09-14-spine-step-names-and-landing in 75c0a8f. osfd is redeployed.

Step names say who acts. Every step is now <actor>.<action>, where the actor is script, openspec, git or human:

  • Setup: git.clone, script.brief, script.agents-md
  • Explore and propose: openspec.explore, openspec.new-change, openspec.propose.{proposal,spec,design,tasks}, openspec.validate, script.budget, git.commit.proposal
  • Review loop: openspec.review, script.review-digest, openspec.revise, git.commit.revision, human.review-proposal
  • Apply: openspec.apply, openspec.reconcile-tasks, openspec.test.unit, git.commit.feature
  • Ship: openspec.summarize, git.commit.summary, git.pr.open
  • Land (new): human.merge-pr, git.pr.merge, human.archive-change, openspec.archive

workspace.prepare is split in two.

  • git.clone says what really happened. The repository was cloned from X into Y, and the work branch was cut from main at a given sha. It also says both happen at admission, before any step runs, and records .osf/workspace.json. It fails if the worktree is not on the run's branch.
  • script.brief writes the brief and prints its first line.

Landing from Braid.

  • human.merge-pr reads the pull request live from Forgejo (the new GET /api/runs/{id}/pr). It offers Merge pull request, which asks in a dialog naming the PR and base branch, and Re-check. If you merged on Forgejo while it waited, Re-check shows it merged and offers Continue — merged on Forgejo.
  • git.pr.merge merges it in the repository's default style. It is refused if the head moved. If the PR was already merged, it just records that.
  • human.archive-change asks in a dialog. openspec.archive then runs openspec archive on the merged base branch, commits, and pushes without force. If the change is already archived, it records that and changes nothing.

Bug fixed: the review and revise loop rows are dim until the run reaches them.

Tested:

  • pytest: 1580 passed. New test_landing.py covers merge, archive and the route against a fake Forge, real openspec and a bare origin.
  • vitest: 353 passed.
  • Playwright: 47 passed, 3 skipped (they need a live run). New landing.spec.ts covers names, the LAND phase, dim loop rows, Cancel/Escape sending nothing, Merge, Re-check open → merged → Continue, and Archive.
  • On a scratch osfd:
    • git.clone printed the clone and branch (below).
    • /api/runs/{id}/pr read the merged #19 from Forgejo.
    • python -m osf.forgejo merge recorded merged_by: forge without asking for a merge.

A repository that commits its own .osf/pipeline.yaml keeps the names in that file, so update it to the new ids. This repository's copy is updated. Runs started before the deploy still carry the old ids and cannot continue.

git.clone on a real osfd:

git-clone-output

The merge gate on an open pull request:

merge-card

Merge pull request asks first:

merge-dialog

After merging on Forgejo and Re-check:

merge-card-merged

Archive change asks first:

archive-dialog

Shipped in 01c21ed, and archived as `2026-09-14-spine-step-names-and-landing` in 75c0a8f. osfd is redeployed. **Step names say who acts.** Every step is now `<actor>.<action>`, where the actor is `script`, `openspec`, `git` or `human`: - **Setup:** `git.clone`, `script.brief`, `script.agents-md` - **Explore and propose:** `openspec.explore`, `openspec.new-change`, `openspec.propose.{proposal,spec,design,tasks}`, `openspec.validate`, `script.budget`, `git.commit.proposal` - **Review loop:** `openspec.review`, `script.review-digest`, `openspec.revise`, `git.commit.revision`, `human.review-proposal` - **Apply:** `openspec.apply`, `openspec.reconcile-tasks`, `openspec.test.unit`, `git.commit.feature` - **Ship:** `openspec.summarize`, `git.commit.summary`, `git.pr.open` - **Land (new):** `human.merge-pr`, `git.pr.merge`, `human.archive-change`, `openspec.archive` **`workspace.prepare` is split in two.** - `git.clone` says what really happened. The repository was cloned from X into Y, and the work branch was cut from `main` at a given sha. It also says both happen at admission, before any step runs, and records `.osf/workspace.json`. It fails if the worktree is not on the run's branch. - `script.brief` writes the brief and prints its first line. **Landing from Braid.** - `human.merge-pr` reads the pull request live from Forgejo (the new `GET /api/runs/{id}/pr`). It offers **Merge pull request**, which asks in a dialog naming the PR and base branch, and **Re-check**. If you merged on Forgejo while it waited, Re-check shows it merged and offers **Continue — merged on Forgejo**. - `git.pr.merge` merges it in the repository's default style. It is refused if the head moved. If the PR was already merged, it just records that. - `human.archive-change` asks in a dialog. `openspec.archive` then runs `openspec archive` on the merged base branch, commits, and pushes without force. If the change is already archived, it records that and changes nothing. **Bug fixed:** the review and revise loop rows are dim until the run reaches them. **Tested:** - `pytest`: 1580 passed. New `test_landing.py` covers merge, archive and the route against a fake Forge, real `openspec` and a bare origin. - `vitest`: 353 passed. - Playwright: 47 passed, 3 skipped (they need a live run). New `landing.spec.ts` covers names, the LAND phase, dim loop rows, Cancel/Escape sending nothing, Merge, Re-check open → merged → Continue, and Archive. - On a scratch osfd: - `git.clone` printed the clone and branch (below). - `/api/runs/{id}/pr` read the merged #19 from Forgejo. - `python -m osf.forgejo merge` recorded `merged_by: forge` without asking for a merge. A repository that commits its own `.osf/pipeline.yaml` keeps the names in that file, so update it to the new ids. This repository's copy is updated. Runs started before the deploy still carry the old ids and cannot continue. `git.clone` on a real osfd: ![git-clone-output](https://forgejo.underthere.xyz/attachments/b8ae78b0-5c6b-4f37-a829-e5ed63b42e1d) The merge gate on an open pull request: ![merge-card](https://forgejo.underthere.xyz/attachments/851a26fa-3047-41c5-a9d5-575b09c7f13f) Merge pull request asks first: ![merge-dialog](https://forgejo.underthere.xyz/attachments/67cfbb35-7944-4112-b3dd-02bfc19d27df) After merging on Forgejo and Re-check: ![merge-card-merged](https://forgejo.underthere.xyz/attachments/931acb77-2999-4d65-9297-e65f9588e15d) Archive change asks first: ![archive-dialog](https://forgejo.underthere.xyz/attachments/39c36cc5-f65a-424a-bb9f-9618449d47a7)
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
cmoriarty/braid#20
No description provided.