diff --git a/README.md b/README.md index 6a8a9eab..d70c7b4c 100644 --- a/README.md +++ b/README.md @@ -871,8 +871,9 @@ requested unused path. Use /import for local checkouts. ### Publishing and GitHub Ask the agent to publish a named source tree or a stack. The `publish_source` tool -pushes the selected code commit directly from the server with an expected-head -lease. The `github` tool runs GitHub CLI for PRs, comments, issues and linking -existing PR URLs into stacks. Add `reader=std/github` alongside `reader=std/llm-step` -in the `github-token` secret. See [publication and stacks](design/agent-publish.md) -for examples, credentials and retry behavior. +pushes one branch; `push_stack` pushes the branches in a registered source stack. +Both push directly from the server with expected-head leases. The `github` tool +runs GitHub CLI for PRs, comments, issues and linking existing PR URLs into stacks. +Add `reader=std/github` alongside `reader=std/llm-step` +in the `github-token` secret. See [GitHub interactions](design/agent-github.md) +for imports, branch publication, stacks, PRs, credentials and retry behavior. diff --git a/SPEC.md b/SPEC.md index 88e0bcf3..b5d5fb36 100644 --- a/SPEC.md +++ b/SPEC.md @@ -634,8 +634,8 @@ An unfinished claim is uncertain; inspect GitHub before proceeding. PR and stack operations compose these tools. Stack boundaries remain gitlinks; publish bottom to top and keep PR membership through GitHub’s stack API. -The TUI's /pr and /publish-branch are removed; /import remains for local paths. -See [agent publication](design/agent-publish.md) for mechanics and recovery. +Use the TUI's /import for local repositories and /checkout for local editing. +See [GitHub interactions](design/agent-github.md) for imports, publication, stacks, PRs and recovery. ## Agent stack updates diff --git a/design/agent-github.md b/design/agent-github.md index aeaf42c5..7542e503 100644 --- a/design/agent-github.md +++ b/design/agent-github.md @@ -1,38 +1,31 @@ -# Importing and publishing +# GitHub interactions -Imports are implemented through the server endpoint, `caos import-git`, and the agent's `import_source` tool. Publication pushes individual branches or registered stacks of branches. Stack operations -keep merge drafts outside source history. +The agent imports code, edits source gitlinks, and publishes their commits as remote branches. It uses GitHub CLI for PRs, reviews, issues and comments. The TUI handles local imports and checkouts. -## Importing +| Workflow | Design | Main tools | +| --- | --- | --- | +| Bring remote code into a conversation | [Importing remote source](agent-import.md), [server fetch and negotiation](git-import.md) | `import_source`, `caos import-git`, `POST /git/import` | +| Publish one source gitlink as a branch | [Publishing branches](agent-publish.md) | `publish_source`, `caos push-git`, `POST /git/push` | +| Update and publish related branches | [Stacks](agent-stacks.md) | `stack`, `push_stack` | +| Create PRs and interact with GitHub | [PRs and GitHub commands](agent-prs.md) | `github`, running `gh` and the pinned `gh stack` extension | -`import_source(source, revision?, into)` runs inline in `std/llm-step`. It accepts an HTTPS repository and a branch, full ref, or full commit hash. Omitting `revision` selects the default branch. Keep -`/import` for local paths. +## How the pieces fit -For each tool call: +A [conversation](chat.md) contains source gitlinks pointing to code commits. Importing attaches an existing commit at a new path. Editing that source advances its gitlink. Publishing sends its exact +commit and history from the server's Git store to a remote branch; it does not move the source gitlink. -1. Resolve the revision with `git ls-remote`, using the agent's existing Git - binary. A full commit hash needs no lookup. -2. Save the chosen hash H and provenance in the conversation's `tool.start` - payload. Resumed attempts reuse H; concurrent attempts use the first saved - observation. A new call resolves the remote again. -3. Run `caos import-git H`. This sends - `POST /git/import {"source": "", "commit": "H"}`. -4. After the server returns `{"commit": "H"}`, atomically attach the snapshot, - its provenance, and the tool result: +A registered stack orders these source gitlinks and remembers the predecessor each layer was based on. The `stack` tool rebases or merges using Git objects, pausing conflicts in a separate draft that +the agent can edit and continue. `push_stack` publishes the layers' branches through the same server path as a single-branch push. - ```text - imports/repo/main gitlink -> H - imports/repo/main.source.json provenance - ``` +The `github` tool runs a worker containing GitHub CLI. It manages remote metadata after branches exist. It needs no source checkout for PR creation, review, or linking existing PR URLs. Source +restacking and branch pushes remain CAOS operations. -The destination and provenance path must both be unused. An import creates an unchanged snapshot; it does not merge into or advance another source. Provenance records the repository, requested -revision, commit, observation time, and default branch when known. For `origin/main`, choose the repository from the selected source's provenance and import `main` at a fresh path. +Stack publication is independent of PRs. It pushes branches and records their results; it does not create PRs or GitHub stack membership. The generic `github` tool can manage those separately. +Automatically submitting all PRs for a stack is a follow-up described in the [PR design](agent-prs.md#prs-for-a-stack). -The [server endpoint](git-import.md) fetches H and its full history into private staging, verifies them, and publishes the complete pack into the server store. It uses verified complete imports as -negotiation tips; standalone trees and blobs may still be downloaded again. A completion marker for the same URL and H skips fetch and verification. The endpoint handles object availability; callers -handle ref resolution and conversation state. +## Credentials -Supply the token through the existing secret store: +Supply a GitHub token through the existing secret store when launching the TUI: ```text # .caos-secrets/github-token @@ -42,21 +35,13 @@ reader=std/llm-step reader=std/github ``` -Keep the value file ignored and run `caos secrets` to initialize its entropy. The agent uses `/secret/github-token` for GitHub ref lookup and passes `--github-token-file=/secret/github-token` to -`import-git`. The command forwards it in the sensitive `X-Caos-Git-Token` header; the server does not look up the calling job's secrets. +Put the token value in an ignored file and run `caos secrets` to initialize its entropy. `std/llm-step` uses the token for GitHub ref lookup and forwards it to the server for imports and pushes. +`std/github` passes it to `gh` as `GH_TOKEN`. -Ref lookup and fetch share a repository-scoped Git credential helper. Tokens stay out of URLs, Git config, saved arguments, provenance, and logs. Automatic GitHub credentials apply only to -`github.com` on the default HTTPS port. Public imports need no token. Importing needs neither `gh` nor another worker. +## Local work and recovery -## Publishing +Use `/checkout` to edit a source locally. Commit the edits with Git, then use `/import` to attach the result at a new conversation path. Ask the agent to integrate that imported commit into the +intended source. See [local editing](chat.md#viewing-files-and-working-locally) for the commands. -[Branch publication](agent-publish.md) uses POST /git/push, caos push-git and publish_source to push exact commits directly from the server with an expected-head lease. The github tool runs gh with an -explicit repository for PRs, issues, review and stack metadata. - -[Stack operations](agent-stacks.md) register ordered source gitlinks, remember each layer's predecessor, and merge or rebase them using Git objects. Conflicts pause with a separate draft gitlink and -report. The agent edits the draft and explicitly continues; finished source history contains no .caos/conflicts or draft editing commits. - -push_stack pushes registered layers through the same server path as publish_source, recording each branch's result. Stack pushing needs no GitHub worker and creates no PRs or GitHub stack membership. -PR automation is a separate follow-up. - -The TUI's /pr and /publish-branch commands are removed. /import remains for local paths. Older non-stack merge operations still use the legacy source-tree conflict ledger. +Imports pin the resolved commit for each call. Pushes pin the source commit and expected remote head before sending. GitHub commands record each invocation so a worker retry does not silently repeat a +write. The linked designs describe each recovery path and what the agent does when the remote outcome is uncertain. diff --git a/design/agent-harness.md b/design/agent-harness.md index ecbd10da..92a3a096 100644 --- a/design/agent-harness.md +++ b/design/agent-harness.md @@ -360,11 +360,10 @@ points is the caller's tree's business, not this client's (`design/chat.md`, and freezes redraws for native terminal text selection. `/checkout [directory]` checks out the named code commit as a detached HEAD in a clean local checkout. `Ctrl+H` opens the keyboard and slash-command reference. - Publication uses the agent's publish_source and github tools. The - server pushes the selected code commit; the GitHub worker handles PRs and - stacks. See [publication](agent-publish.md) for frozen inputs, leases and - recovery. The TUI's /pr and /publish-branch are removed. Publishing source - commits never mutates the local checkout. + Publication uses the agent's publish_source and push_stack tools. The + server pushes code commits; the GitHub worker handles PRs and other GitHub + metadata. See [GitHub interactions](agent-github.md) for the designs and recovery. + Publishing source commits never mutates the local checkout. ### Superseded protocol detail diff --git a/design/agent-import.md b/design/agent-import.md new file mode 100644 index 00000000..2ee12f54 --- /dev/null +++ b/design/agent-import.md @@ -0,0 +1,33 @@ +# Importing remote source + +Part of [GitHub interactions](agent-github.md). This page describes the agent workflow; [git-import.md](git-import.md) describes the server endpoint and fetch negotiation. + +`import_source(source, revision?, into)` runs inline in `std/llm-step`. It accepts an HTTPS repository and a branch, full ref, or full commit hash. Omitting `revision` selects the default branch. Use +`/import` for local paths. + +For each tool call: + +1. Resolve the revision with `git ls-remote`, using the agent's existing Git + binary. A full commit hash needs no lookup. +2. Save the chosen hash H and provenance in the conversation's `tool.start` + payload. Resumed attempts reuse H; concurrent attempts use the first saved + observation. A new call resolves the remote again. +3. Run `caos import-git H`. This sends + `POST /git/import {"source": "", "commit": "H"}`. +4. After the server returns `{"commit": "H"}`, atomically attach the snapshot, + its provenance, and the tool result: + + ```text + imports/repo/main gitlink -> H + imports/repo/main.source.json provenance + ``` + +The destination and provenance path must both be unused. An import creates an unchanged snapshot; it does not merge into or advance another source. Provenance records the repository, requested +revision, commit, observation time, and default branch when known. For `origin/main`, choose the repository from the selected source's provenance and import `main` at a fresh path. + +The [server endpoint](git-import.md) fetches H and its full history into private staging, verifies them, and publishes the complete pack into the server store. It uses verified complete imports as +negotiation tips; standalone trees and blobs may still be downloaded again. A completion marker for the same URL and H skips fetch and verification. The endpoint handles object availability; callers +handle ref resolution and conversation state. + +Configure the [GitHub token](agent-github.md#credentials) for private GitHub repositories. The agent uses it for ref lookup and passes `--github-token-file=/secret/github-token` to `import-git`, which +forwards the token to the server for the fetch. Public imports need no token. diff --git a/design/agent-prs.md b/design/agent-prs.md new file mode 100644 index 00000000..8ede1ceb --- /dev/null +++ b/design/agent-prs.md @@ -0,0 +1,76 @@ +# Pull requests and GitHub commands + +Part of [GitHub interactions](agent-github.md). CAOS publishes branches from the server; the `github` tool runs GitHub CLI to create and update PRs, read reviews, and work with issues and comments. + +## GitHub worker + +`std/github` contains Git, `gh`, and the pinned `github/gh-stack` v0.1.1 extension. It is registered as a built-in tool, available without a project-defined `caos-tools` entry. + +The tool is `github(repository, args, stdin?)`. `args` is an argument array passed directly to `gh`; it is never interpolated into a shell command. Return exit status, stdout and stderr through +ordinary tool results. This covers issues, comments, PR creation/editing and stack operations without separate wrappers for each GitHub action. Pass PR bodies through stdin (`--body-file -`). + +The worker sets `GH_REPO` explicitly and reads `GH_TOKEN` from its granted `/secret/github-token`. Use the [shared token setup](agent-github.md#credentials), granting it to both `std/github` and +`std/llm-step`. The latter uses it for import/push and includes that identity in the model turn’s cache key. The agent carries the GitHub worker source and evaluates it when called, so secret marking +of the child worker does not alter the agent’s own reader identity. Use an isolated temporary GitHub configuration and disable prompts. Install the extension in the image. The worker needs no source +checkout or local branches for the operations below. + +## Invocation recovery + +Identical GitHub commands can observe different remote state, and comments must not be posted again when a worker retries. The harness therefore binds a stable, unique invocation ID into every GitHub +request. A new tool call gets a new ID; resuming the same call retains it. Normal result caching then belongs to that observation, rather than to the command arguments indefinitely. + +A unique cache key alone does not prevent duplicate execution. Before running `gh`, the worker atomically claims a small record under `refs/caos/github/` using the existing Git +compare-and-swap transport. The record binds the entire pinned ArgTree (arguments, worker image, secret identity and salt) and a unique attempt ID. Recovery dispatches the stored task, including its +original worker image. Reusing an invocation with a different ArgTree is an error; changed worker or secret identity requires a new invocation, after reconciling any earlier write. This preserves +result-cache identity and prevents sharing results across credentials. + +A failed claim with no retained ref is a retryable job failure. Once gh has run, retry output storage and result-CAS bookkeeping up to three times, without rerunning gh. Exhausted bookkeeping leaves +the claim uncertain. + +Only the attempt that owns the claim executes the command. Record the exit status and output hashes afterwards; completed duplicates return that result. + +If a claim exists without a recorded result, a duplicate reports pending or uncertain and does not execute `gh`. Never expire or steal that claim based on elapsed time. A crash between claiming and +execution can therefore require inspection even when nothing happened. This provides at most one wrapper execution per invocation, not a transaction or exactly-once guarantee at GitHub. + +Apply this rule to all commands, including reads, to avoid classifying arbitrary `gh api` requests as safe or unsafe. After an uncertain write, the agent uses a new read invocation to inspect GitHub, +then decides the remaining action. An absent PR or comment is not proof that a still-running command cannot create it. If reconciliation cannot establish the outcome, leave it uncertain rather than +repeat the write. Failure of a multi-step command can leave partial changes. The tool's exit status and transcript must not claim that nothing happened. + +## PR workflow + +For a single PR: + +1. Integrate required updates and test the chosen source gitlink. +2. Call [`publish_source`](agent-publish.md) with its path, repository and remote branch. Continue + after a confirmed push. +3. Find an open PR with `gh pr list --head `; select explicitly if + several match. If absent, use `gh pr create --repo + --head --base --title --body-file -`, passing the + body through the tool's stdin. Supply these arguments explicitly so + creation needs no local repository. +4. Check the PR's URL, head commit and base with `gh pr view <url> --json ...`, + and retain the result in the conversation. + +Later source edits advance the same branch through `publish_source`, updating the existing PR. Preserve human-edited titles and descriptions unless an edit was requested; use `gh pr edit` for +requested metadata or base changes. Use `gh pr view`, `gh pr checks`, and `gh api` to read discussion, review threads and checks, and the corresponding CLI/API calls for requested replies. Create +ready-for-review PRs by default. A failed PR creation leaves the successful branch push intact; recovery follows the invocation rules above. + +## PRs for a stack + +[Stack publication](agent-stacks.md#pushing-branches) produces ordinary remote branches. For example, a two-layer stack based on remote `main` maps to: + +| Source gitlink | PR head branch | PR base branch | +| --- | --- | --- | +| `feature/01-core` | `feature/01-core` | `main` | +| `feature/02-ui` | `feature/02-ui` | `feature/01-core` | + +The base gitlink has no PR. The first PR targets the remote integration branch; each later PR targets the preceding layer's branch. PR numbers are assigned by GitHub and can be discovered from the +repository and branch names. Keep the returned URLs in the conversation for later review and updates. + +The agent can perform these steps with the generic `github` tool after a confirmed `push_stack`. There is no dedicated operation that creates or repairs all PRs for a stack. That automation remains a +follow-up. + +GitHub stack membership is also separate from branch publication. Once PRs exist, the worker can pass their URLs to `gh stack link`. Using PR URLs avoids the extension's local-branch push workflow; +CAOS remains responsible for moving the branch refs. The source gitlinks and `stack.json` remain the inputs to CAOS restacking, not GitHub's PR metadata. + +Implementation: [GitHub worker](../std/github/src/main.rs) and [agent tool](../std/llm-step/src/github.rs). diff --git a/design/agent-publish.md b/design/agent-publish.md index 85c073bc..2d71c021 100644 --- a/design/agent-publish.md +++ b/design/agent-publish.md @@ -1,20 +1,25 @@ -# Agent publication +# Publishing branches -CAOS publishes exact code commits from its server. The GitHub worker manages PR metadata. See [agent-stacks.md](agent-stacks.md) for stack registration, restacking, conflict resolution and branch -publication. - -## Branches +Part of [GitHub interactions](agent-github.md). This page covers one branch; [stack publication](agent-stacks.md#pushing-branches) uses the same path for each layer. [PRs](agent-prs.md) are created +after publication. The server publishes code commits directly from its bare Git store, without checking out source files. -| Layer | Interface | | --- | --- | | Server | `POST /git/push {destination, commit, branch, expected, rewrite?}` | | Worker command | `caos push-git <https-url> <commit> <branch> ---expected=<oid\|absent>` | | Agent tool | `publish_source(source_tree, repository, branch, rewrite?)` | +| Layer | Interface | +| --- | --- | +| Server | `POST /git/push {destination, commit, branch, expected, rewrite?}` | +| Worker command | `caos push-git <https-url> <commit> <branch> --expected=<oid\|absent>` | +| Agent tool | `publish_source(source_tree, repository, branch, rewrite?)` | The request fields are: -| Field | Meaning | | --- | --- | | `destination` | Remote repository's HTTPS URL, e.g. `https://github.com/owner/repo.git`. | | `commit` | Full hash H of the code commit to publish, already stored in -CAOS. | | `branch` | Destination branch in that remote, e.g. `feature/parser`, without `refs/heads/`. | | `expected` | Full hash E expected at that same remote branch, or JSON `null` if it must not -exist. Required; the CLI spells `null` as `absent`. | | `rewrite` | Optional boolean, default false. Permit a non-fast-forward update while still requiring the exact expected remote head. | +| Field | Meaning | +| --- | --- | +| `destination` | Remote repository's HTTPS URL, e.g. `https://github.com/owner/repo.git`. | +| `commit` | Full hash H of the code commit to publish, already stored in CAOS. | +| `branch` | Destination branch in that remote, e.g. `feature/parser`, without `refs/heads/`. | +| `expected` | Full hash E expected at that remote branch, or JSON `null` if it must not exist. Required; the CLI spells `null` as `absent`. | +| `rewrite` | Optional boolean, default false. Permit a non-fast-forward update while requiring the exact expected remote head. | `refs/heads/feature/parser` is Git's full name for the branch `feature/parser`. Ordinary branch pushes can infer this prefix from a local branch. Since CAOS pushes a commit hash, it explicitly names the remote branch: @@ -35,7 +40,7 @@ The endpoint performs one push: the ancestry check for an intentional rebased-history update. Reject H if its tree contains paths matched by its own .gitignore rules. 3. Push H to the destination branch with - --force-with-lease=refs/heads/<branch>:<E>, disabling tag following. + `--force-with-lease=refs/heads/<branch>:<E>`, disabling tag following. Empty E requires creation. The default permits only creates and fast-forwards; rewrite: true allows a history rewrite while retaining that exact lease. Duplicate requests to the same branch are serialized. @@ -43,8 +48,8 @@ The endpoint performs one push: per-ref receiver rejections are definite failures. Unconfirmed transport failures are uncertain. The CLI preserves these results for llm-step. -The endpoint does not fetch, import, merge, rebase, rewrite commits, or perform a follow-up remote lookup. Objects transfer directly from CAOS to the destination through Git. Reuse import -authentication: token-file option, sensitive header and repository-scoped credential helper. +The endpoint does not fetch, import, merge, rebase, rewrite commits, or perform a follow-up remote lookup. Objects transfer directly from CAOS to the destination through Git. Use the [shared +credentials](agent-github.md#credentials) through the token-file option, sensitive header and repository-scoped credential helper. llm-step owns the workflow. It selects a source gitlink, resolves conflicts, tests and inspects the diff, then reads its commit H and the remote head E. Before sending, it records H, E, destination and branch under the tool-call identity. Every attempt may send that same pinned intent; recovery never substitutes a newer commit or refreshes the lease. Publishing leaves the source gitlink @@ -53,9 +58,10 @@ unchanged. On a lease conflict, llm-step can separately import the remote head, merge or rebase, test, and make a new publication call. Other rejections carry their reason through the CLI to the tool result. Importing and integration are never hidden inside a push. -A remote can accept a push before the connection drops. Git's HTTP retry can then report a stale lease. After a receiver conflict or uncertain result, llm-step reads the branch: H confirms completion. -Otherwise it preserves a definite rejection; for uncertainty, another value than E is a conflict, while E or a failed lookup remains uncertain because a push may still be running. The endpoint itself -does no recovery. A success receipt records the original push even if the branch later advances. +A remote can accept a push before the connection drops. Git's HTTP retry can then report a stale lease. After a receiver conflict, uncertain result, or unreadable successful command result, llm-step +reads the branch: H confirms completion. Otherwise it preserves a definite rejection; for uncertainty, another value than E is a conflict, while E or a failed lookup remains uncertain because a push +may still be running. The endpoint itself does no recovery. A success receipt records the original push even if the branch later advances. The agent saves the receipt before completing the tool call, +so a restart can finish from that saved result. Publication transfers the exact commit. Before pushing, the server checks H's tree against its versioned .gitignore files, including nested rules and negations. A match returns HTTP 422 with code `ignored-files`; the CLI and agent retain this as a definite rejection without remote reconciliation. Git performs the check using a private index; no source files are checked out. @@ -66,78 +72,7 @@ not earlier commits; a file added and deleted in its history is outside this che Local Git staging still respects .gitignore for untracked files. Imports keep their exact commits, and agent tools continue to capture files as they do today. Ignored scratch files can therefore remain in a source during work; the agent must remove them or adjust the rules before publication. -Registered stacks keep conflicts in a separate draft gitlink and report, outside source history. Older merge operations can still create a .caos/conflicts ledger; resolve it before publishing. The -generic endpoint does not scan for that ledger, inline markers, or conversation ancestry. - -## PRs - -`std/github` contains Git, `gh`, and the pinned `github/gh-stack` v0.1.1 extension. It is registered as a built-in tool, available without a project-defined `caos-tools` entry. - -The tool is `github(repository, args, stdin?)`. `args` is an argument array passed directly to `gh`; it is never interpolated into a shell command. Return exit status, stdout and stderr through -ordinary tool results. This covers issues, comments, PR creation/editing and stack operations without separate wrappers for each GitHub action. Initially use stdin for bodies (`--body-file -`); -commands needing local file attachments can be added when needed. - -The worker sets `GH_REPO` explicitly and reads `GH_TOKEN` from its granted `/secret/github-token`. Add `reader=std/github` to the existing secret; `std/llm-step` also needs the grant: it uses the -token for import/push and includes that identity in the model turn’s cache key. The agent carries the GitHub worker source and evaluates it when called, so secret marking of the child worker does not -alter the agent’s own reader identity. Use an isolated temporary GitHub configuration and disable prompts. Install the extension in the image. The worker needs no source checkout or local branches for -the operations below. - -### Invocation recovery - -Identical GitHub commands can observe different remote state, and comments must not be posted again when a worker retries. The harness therefore binds a stable, unique invocation ID into every GitHub -request. A new tool call gets a new ID; resuming the same call retains it. Normal result caching then belongs to that observation, rather than to the command arguments indefinitely. - -A unique cache key alone does not prevent duplicate execution. Before running `gh`, the worker atomically claims a small record under `refs/caos/github/<invocation-id>` using the existing Git -compare-and-swap transport. The record binds the entire pinned ArgTree (arguments, worker image, secret identity and salt) and a unique attempt ID. Recovery dispatches the stored task, including its -original worker image. Reusing an invocation with a different ArgTree is an error; changed worker or secret identity requires a new invocation, after reconciling any earlier write. This preserves -result-cache identity and prevents sharing results across credentials. - -A failed claim with no retained ref is a retryable job failure. Once gh has run, retry output storage and result-CAS bookkeeping up to three times, without rerunning gh. Exhausted bookkeeping leaves -the claim uncertain. - -Only the attempt that owns the claim executes the command. Record the exit status and output hashes afterwards; completed duplicates return that result. - -If a claim exists without a recorded result, a duplicate reports pending or uncertain and does not execute `gh`. Never expire or steal that claim based on elapsed time. A crash between claiming and -execution can therefore require inspection even when nothing happened. This provides at most one wrapper execution per invocation, not a transaction or exactly-once guarantee at GitHub. - -Apply this rule to all commands, including reads, to avoid classifying arbitrary `gh api` requests as safe or unsafe. After an uncertain write, the agent uses a new read invocation to inspect GitHub, -then decides the remaining action. An absent PR or comment is not proof that a still-running command cannot create it. If reconciliation cannot establish the outcome, leave it uncertain rather than -repeat the write. Failure of a multi-step command can leave partial changes. The tool's exit status and transcript must not claim that nothing happened. - -### PR workflow - -For a single PR: - -1. Integrate required updates and test the chosen source gitlink. -2. Call `publish_source` with its path, repository and remote branch. Continue - after a confirmed push. -3. Find an open PR with `gh pr list --head <branch>`; select explicitly if - several match. If absent, use `gh pr create --repo <repository> - --head <branch> --base <base> --title <title> --body-file -`, passing the - body through the tool's stdin. Supply these arguments explicitly so - creation needs no local repository. -4. Check the PR's URL, head commit and base with `gh pr view <url> --json ...`, - and retain the result in the conversation. - -Later source edits advance the same branch through `publish_source`, updating the existing PR. Preserve human-edited titles and descriptions unless an edit was requested; use `gh pr edit` for -requested metadata or base changes. Use `gh pr view`, `gh pr checks`, and `gh api` to read discussion, review threads and checks, and the corresponding CLI/API calls for requested replies. Create -ready-for-review PRs by default. A failed PR creation leaves the successful branch push intact; recovery follows the invocation rules above. - -## Stacks - -A registered stack consists of ordered source gitlinks and a manifest recording each layer's old predecessor. CAOS updates these commits using Git's object-based merge engine and retains paused -conflicts outside source history. See [the stack workflow](agent-stacks.md) for the representation and tool calls. - -`push_stack(path, repository, rewrite?)` pins all source commits and remote-head leases, then pushes branches bottom to top using the same publication path as `publish_source`. It records each outcome -before proceeding and reports partial progress if a later branch fails. Recovery retains the original pins and skips completed branches. - -Pushing branches is independent of PR creation and GitHub stack membership. The conversation manifest records the intended order; the remote receives branch refs and commit ancestry. Automated PR -submission is a separate follow-up. - -## Interfaces - -The agent uses publication and GitHub tools for PR operations. The TUI's publication commands and preview UI are removed. Existing publication records remain readable. Local imports keep their TUI -command. +Registered stacks keep conflicts in a separate draft gitlink and report, outside source history. The `merge` tool can produce a `.caos/conflicts` ledger; resolve it before publishing. The endpoint +does not scan for that ledger, inline markers, or conversation ancestry. -Implementation: [server push endpoint](../rust/crates/server/src/push.rs), [agent publication](../std/llm-step/src/publish_source.rs), [GitHub worker](../std/github/src/main.rs), and [stack -tools](../std/llm-step/src/stack.rs). +Implementation: [server endpoint](../rust/crates/server/src/push.rs), [worker command](../rust/crates/caos/src/push_git.rs), and [agent tool](../std/llm-step/src/publish_source.rs). diff --git a/design/agent-stacks.md b/design/agent-stacks.md index e6408121..6618e566 100644 --- a/design/agent-stacks.md +++ b/design/agent-stacks.md @@ -1,5 +1,7 @@ # Agent stacks +Part of [GitHub interactions](agent-github.md). This page covers source history and branch publication; [PRs and GitHub stack membership](agent-prs.md#prs-for-a-stack) are separate. + A stack is an ordered list of source gitlinks. Git computes merges directly from objects; CAOS records the order and any paused operation. Publication pushes the stack's branches directly from the server. diff --git a/design/chat.md b/design/chat.md index 86a34af1..e1c868c0 100644 --- a/design/chat.md +++ b/design/chat.md @@ -2,8 +2,9 @@ A conversation has one filesystem. It holds messages and protocol metadata under `.caos/`, ordinary files such as notes and memories, and references to code. -The agent imports HTTPS repositories into this filesystem. The TUI imports -local checkouts, exports code for local editing, and publishes to remotes. +The agent imports HTTPS repositories into this filesystem and publishes code to remotes. The TUI imports local checkouts and exports code for local editing. + +See [GitHub interactions](agent-github.md) for the import, branch publication, stack and PR workflows. | Name | Meaning | | --- | --- | @@ -153,7 +154,7 @@ completion markers certify full history and allow object reuse. The handler atomically records its result and attaches the gitlink/provenance only if both paths remain free. Replays do not add another result. Imports do not merge into existing code. Local paths still use `/import` below. -See [agent-github.md](agent-github.md#importing) for credential and retry details. +See [importing remote source](agent-import.md) for credentials and retry details. ## Importing code with `/import` @@ -348,22 +349,18 @@ a clean Git checkout or an empty/new directory. The client remembers that destination locally, keyed by server, conversation, and gitlink path. A later `/checkout feature/01-change` can reuse it. -`/update-tree feature/01-change <message>` commits edits in that path's remembered -checkout, submits them back to that source, and continues the conversation with -the user's message. The source path is explicit in both commands. +Commit local edits with Git, then import the checkout at an unused conversation +path, for example `/import imports/local-edit /absolute/path/to/checkout`. +Ask the agent to integrate that imported commit into the intended source gitlink. +The imported snapshot remains separate until that integration. Browser selection does not choose checkout or publication targets, and does not change the agent's execution context. ## Publishing -The agent uses publish_source(source_tree, repository, branch) to publish an -exact code commit and github(repository, args, stdin?) for PRs and stacks. -Publication receipts remain in the conversation; source gitlinks do not move. -The TUI's /pr and /publish-branch commands are removed. +The agent uses `publish_source` for one branch, `stack` to update related source histories, `push_stack` to publish their branches, and `github` for PRs and other GitHub operations. Publication +receipts remain in the conversation; publishing does not move source gitlinks. -See [agent publication and stacks](agent-publish.md) for the server endpoint, -leases, invocation records and stack updates. The agent checks the complete -PR scope and tests before publication. Integrating upstream retains inherited -changes; transplanting only a small edit onto a different base is a separate -operation. +[GitHub interactions](agent-github.md) is the entry point for these designs. The agent checks the complete PR scope and tests before publication. Integrating upstream retains inherited changes; +transplanting only a small edit onto a different base is a separate operation. diff --git a/design/git-import.md b/design/git-import.md index a7240575..eb81a58c 100644 --- a/design/git-import.md +++ b/design/git-import.md @@ -79,7 +79,7 @@ credentials, like other objects already in the store. Implementation: [endpoint](../rust/crates/server/src/import.rs), [Git command and credential setup](../rust/crates/git-locator/src/import.rs). -Caller behavior: [agent imports](agent-github.md#importing). +Caller behavior: [agent imports](agent-import.md). Overview: [GitHub interactions](agent-github.md). ## Object-store invariant