feat(discord): git verbs for the Discord Sage on the shared-signals root, seat identity through a package credential helper, vault record protocol (#1509)

Row 24. A writable root that is a git work tree may carry a git object in
the binding; the seat then has git_status, git_commit (explicit paths, seat
author, Requested-by trailer from the envelope requester, push at once per
D6), git_pull (ff-only) and git_push (one branch, never force), plus
reserve_id and per-write clone locks under protocol vault. Git children run
with no host config and one credential helper, bin/git-credential.mjs,
reading the 0600 seat token file named in the binding; the fleet helper
serves only the Gitea hosts. Suite 58/58, node 143. rev-code-02 APPROVED
round 1 (#1509 comment 26375, tree 82ab962f).

Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
2026-09-18 07:52:35 -05:00
co-authored by Claude Fable 5.1
parent 1685deb423
commit 1949ed8d31
23 changed files with 1284 additions and 48 deletions
+29 -11
View File
@@ -19,9 +19,11 @@ fixed argument list, run only in a root that is marked `"write": true`
and is a git work tree. No verb takes free-form arguments.
- `git_status(root)`: branch, ahead/behind, changed paths. Read only.
- `git_commit(root, message, paths?)`: stages the named paths (or every
change under the root when omitted), refuses a dot-prefixed path or a
path outside the root, refuses an empty message or one over 500
- `git_commit(root, message, paths)`: stages exactly the named paths
(one to fifty; the "every change when omitted" form of the first draft
was dropped for section 6's explicit-path rule, since the root is
Jason's own clone), refuses a dot-prefixed path or a
path outside the root, refuses when the index already holds staged work, refuses an empty message or one over 500
characters, refuses when nothing is staged, commits with author
`Sage <[email protected]>` and a trailer naming the Discord author
by role (`Requested-by: Jason` or `Carmen`, never an id). Returns the
@@ -38,18 +40,34 @@ the one the binding names (`"branch": "main"`), so a detached head or
another branch refuses; 60 s timeout; stdout and stderr are captured,
trimmed to 4 KiB and returned as data; exit codes become fixed refusals.
Credentials: the connector already runs with `MOSAIC_AGENT_NAME=sage`.
The engine adds `MOSAIC_GIT_IDENTITY=sage` to the child environment and
the repository's existing helper (`git-credential-mosaic`) resolves the
seat's GitHub token at push time. The token is never read, printed,
journaled or passed as an argument; a push failure returns git's message
with any `https://…@` form masked.
Credentials, as built (2026-09-18; the draft above said the fleet helper
would serve): `~/.mosaic/tools/git/git-credential-mosaic` answers only
the two Gitea hosts and exits silently for github.com, and the host's
global git config sends github.com to Jason's own `gh` login. Neither is
acceptable for Sage, so the verbs run git with `GIT_CONFIG_GLOBAL=/dev/null`,
`GIT_CONFIG_NOSYSTEM=1`, no askpass, no prompt, and one helper set
through `GIT_CONFIG_COUNT`: the package's `bin/git-credential.mjs`,
which answers `get` over https from the 0600 file the binding names in
`tokenFile`. The connector checks the file's mode at load and never reads
it; the path reaches git only for push, pull and reserve, through the
environment, never as an argument. The token is never read by the
connector, printed, journaled or passed as an argument; a push failure
returns git's message with any `https://…@` form and token shape masked.
The D5 identity (seat token, `Sage <[email protected]>`) is unchanged;
only the mechanism that presents it differs from the draft.
Binding (`tools` key, fixed):
The requester in the trailer is the Discord author's server name, which
the connector now writes into the envelope line (`requester="…"`) and the
extension reads on `before_agent_start`. A turn without a requester
cannot commit.
Binding (`tools` key, fixed), as built:
```json
{ "name": "shared-signals", "path": "…/shared-signals", "write": true,
"git": { "branch": "main", "identity": "sage" } }
"git": { "branch": "main", "identity": "sage",
"tokenFile": "…/secrets/github-jetrich-sage.token",
"author": "Sage <[email protected]>", "protocol": "vault" } }
```
Without `git` on a root, no git verbs are offered for it. The prompt