Compare commits

..
3 Commits
Author SHA1 Message Date
fargo 74a692fd81 style(ri-050): TASKS.md formatting with repo-pinned prettier 3.8.1 (#1275)
ci/woodpecker/pr/ci Pipeline was successful
2026-08-18 20:04:54 -05:00
fargo 9abf3a5124 style(ri-050): prettier formatting for evidence pack tables (#1275)
ci/woodpecker/pr/ci Pipeline failed
2026-08-18 19:51:46 -05:00
fargo 12b37c097f docs(ri-050): release evidence pack — RI-050 floor evidenced, registry credential proven (pipeline 2517) (#1275)
ci/woodpecker/pr/ci Pipeline failed
2026-08-18 19:37:40 -05:00
7 changed files with 134 additions and 299 deletions
+4 -4
View File
@@ -16,17 +16,17 @@
> the PR head, squash merge to `next`, and acceptance evidence in notes.
| id | status | description | issue | agent | repo | branch | depends_on | estimate | notes |
| -------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- | ---------- | ----------------- | --------------------------------- | ---------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| -------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- | ---------- | ----------------- | --------------------------------- | ---------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| RI-0-001 | done | Bootstrap: issue #1275, PRD section, this DAG, scratchpad (docs only) | #1275 | pi-glm-5.3 | mosaicstack/stack | docs/ri-050-mission-bootstrap | — | 6K | PR #1276 (head 758659dd): docs-only, CI green (2475). Review requested from fargo. Merges first (no publish run). |
| RI-1-001 | done | RI-N1: canonical terminal verification command + publish-pipeline exact-commit gate (every publish step depends on verify; commit identity check; fail closed) | #1275 | pi-glm-5.3 | mosaicstack/stack | feat/ri-050-publish-gate | RI-0-001 | 25K | PR #1277 (head 46784c8d): CI GREEN at head after serialized retry (pipeline 2476, 2026-08-18) - earlier red was CI-agent contention (web SPA timeouts under concurrent pipelines), not code. Review requested from fargo at pinned head (comms 20260818T021025Z). |
| RI-1-002 | done | RI-N1 negative control: checked-in tests proving a broken mandatory check blocks every publish step and that DAG edges cannot be bypassed | #1275 | pi-glm-5.3 | mosaicstack/stack | test/ri-050-publish-gate-negative | RI-1-001 | 12K | |
| RI-2-001 | done | RI-N2 (Forge): remove stub-executor false success; `--simulate` typed `simulated` results that satisfy nothing; literal-`true` gates and echo-review replaced with real gates or typed waiting-for-authority | #1275 | pi-glm-5.3 | mosaicstack/stack | fix/ri-050-forge-fail-closed | RI-0-001 | 20K | Independent review APPROVED 2026-08-17 (Gitea review 172 on PR #1278, head 99b8f6ea; reviewing seat fargo — recorded under shared host principal mos-dt-0, provenance correction posted by fred; wrapper gap filed by fred). Executed at head: forge tests 116/116, lint green, typecheck green after building macp dist (minimal-install artifact, not a defect), workspace typecheck 45/45, no external type consumers of the changed interfaces. CI red = known lane-wide fleet-test failure only, carries no information about this change (fred, log-content analysis, pipelines 2456-2458). Non-blocking finding: README L141-143 + skills/mosaic-forge/SKILL.md document bare forge run/resume, which now fails closed — fast-follow docs touch. Merge queued behind #1270. UPDATE 2026-08-18: #1270 merged; CI GREEN at head 4917df1f via serialized retry (pipeline 2477) - root cause of prior reds was CI-agent contention (web SPA timeouts under concurrent pipelines), superseding the fleet-test-failure theory. |
| RI-2-002 | done | RI-N2 (MACP): gate runner fails closed on empty commands, stub executors, and unimplemented CI-provider gates unless explicit simulate; typed capability failures | #1275 | pi-glm-5.3 | mosaicstack/stack | fix/ri-050-macp-fail-closed | RI-0-001 | 15K | PR #1293 (head 2097379e): CI green (pipeline 2465), independent review APPROVED (Gitea review 173, jarvis seat, 2026-08-17) - macp 109/109 verified at head. Merge queued behind #1276/#1277/#1278. |
| RI-3-001 | done | RI-N4: complete probe inventory mapping every TS and shell quality-rail check to one canonical check with disposition (preserve/strengthen/retire, each named) | #1275 | pi-glm-5.3 | mosaicstack/stack | docs/ri-050-qr-probe-inventory | RI-0-001 | 12K | PR #1302 (head e06a47fac591): CI green (2484), independent review APPROVED (Gitea review 187, fargo seat, 2026-08-18) — 54 rows / 21 canonical checks / dispositions 43-2-9-0 verified by row-count and code spot-checks. Merged by fargo at pinned head. |
| RI-3-002 | not-started | RI-N4: TS evaluator absorbs effective shell probes; typed results (passed/failed/blocked/error/not-applicable) with versioned digested check definitions; shell commands become thin adapters; contract/parity/negative-control tests | #1275 | pi-glm-5.3 | mosaicstack/stack | feat/ri-050-qr-evaluator | RI-3-001 | 30K | |
| RI-4-001 | in-progress | RI-N3: one PRD application service — `mission --plan` persists mission↔PRD linkage (ids/versions/selected requirements); `mosaic prdy` routes through the service or becomes a named import/export adapter; Markdown is a labeled generated view; explicit conflict-aware import | #1275 | pi-glm-5.3 | mosaicstack/stack | feat/ri-050-prd-authority | RI-0-001 | 35K | PR #1294 (head 8d258e1d): CI green (pipeline 2466), independent review APPROVED (Gitea review 174, jarvis seat, 2026-08-17) - prdy 20/20 + command specs 9/9 at head. Merge queued behind #1276/#1277/#1278. |
| RI-3-002 | done | RI-N4: TS evaluator absorbs effective shell probes; typed results (passed/failed/blocked/error/not-applicable) with versioned digested check definitions; shell commands become thin adapters; contract/parity/negative-control tests | #1275 | pi-glm-5.3 | mosaicstack/stack | feat/ri-050-qr-evaluator | RI-3-001 | 30K | | PR #1308 (head 68279d61): CI green (2506), independent review APPROVED (Gitea review 188, fred, seven mutations incl. vacuous-pass + stage-removal). Merged by fargo at pinned head → next @ 245e0c4. Follow-up #1309 (digest wording). |
| RI-4-001 | done | RI-N3: one PRD application service — `mission --plan` persists mission↔PRD linkage (ids/versions/selected requirements); `mosaic prdy` routes through the service or becomes a named import/export adapter; Markdown is a labeled generated view; explicit conflict-aware import | #1275 | pi-glm-5.3 | mosaicstack/stack | feat/ri-050-prd-authority | RI-0-001 | 35K | PR #1294 (head 8d258e1d): CI green (pipeline 2466), independent review APPROVED (Gitea review 174, jarvis seat, 2026-08-17) - prdy 20/20 + command specs 9/9 at head. Merge queued behind #1276/#1277/#1278. | PR #1294 (head 8d258e1d): CI green (2466), review 174. Merged 2026-08-18 overnight wave → next @ d92de53. |
| RI-5-001 | done | RI-N5: typed freshness states (current/stale/partial/unknown/unavailable); no failed-fetch-renders-empty; stale derived verdicts → unknown; mutations disabled when stale; failure-matrix tests | #1275 | pi-glm-5.3 | mosaicstack/stack | feat/ri-050-web-stale-safety | RI-0-001 | 25K | |
| RI-V-001 | not-started | Final verification + release evidence: all cards verified merged, negative controls demonstrated, real `next` publish run green on exact commit, evidence pack recorded | #1275 | pi-glm-5.3 | mosaicstack/stack | docs/ri-050-release-evidence | RI-1-002, RI-2-001, RI-2-002, RI-3-002, RI-4-001, RI-5-001 | 10K | |
| RI-V-001 | in-progress | Final verification + release evidence: all cards verified merged, negative controls demonstrated, real `next` publish run green on exact commit, evidence pack recorded | #1275 | pi-glm-5.3 | mosaicstack/stack | docs/ri-050-release-evidence | RI-1-002, RI-2-001, RI-2-002, RI-3-002, RI-4-001, RI-5-001 | 10K | | Evidence pack live on branch docs/ri-050-release-evidence — all five requirements evidenced; registry credential fixed (jarvis, #1275 c23239) and PROVEN green: pipeline 2517 (retry of 2512, identical commit) all steps green incl. build-gateway; pack PR next, then topher review + merge, close #1275. |
## Dispatch waves (max 2 parallel workers)
+121
View File
@@ -0,0 +1,121 @@
# RI-050 Release Evidence Pack (alpha 0.0.50 release-integrity floor)
> Status: **DRAFT — proof complete, awaiting review + merge**. All five normative requirements (RI-N1..N5) merged to `next` behind the live gate. Registry credential fixed 2026-08-18 23:47Z and **proven end-to-end**: push pipeline **2517** (retry of failed 2512 at the identical commit d4d32a8, only the secret changed between runs) — all steps green including `build-gateway`. Remaining for closure: this pack PR reviewed (topher), merged to `next`, its own push pipeline green, #1275 closed. Last updated 2026-08-19 by fargo (day-takeover orchestrator).
> Card: RI-V-001. All sections marked ⏳ pending their card's merge. Normative source:
> `docs/PRD.md` § Release Integrity Workstream (#1275).
## RI-N1 — Canonical terminal verification + exact-commit publish gate
| exhibit | evidence | where |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------- |
| Gate live, fail-closed | Push pipeline **2486**: `verify` ran at exact commit, FAILED on a real latent defect (gateway cross-user-isolation cleanup on the no-DB path), and `build` / `publish-npm` / `build-gateway` were all **skipped**. First push in repo history that did not publish ungated (prior ungated publishes beside failing builds: 2439, 2462, 2482). | Woodpecker repo 47 pipeline 2486 |
| Gate-caught defect fixed | PR **#1304** (afterAll honors `dbAvailable`; both paths verified: dead-port 28 skipped + file passes; live-5433 28 passed). Review 180 (fred). | PR #1304 |
| First gated green npm publish | Push pipeline **2488** (post-#1304): `verify` GREEN → `build` GREEN → `publish-next-npm` GREEN, all publish effects behind the gate. | Woodpecker pipeline 2488 |
| Negative controls | PR **#1305**: structural DAG tests (S1 missing edge, S2 renamed effect incl. command-based npm/kaniko detection, S3 detach, S4 failure:ignore/success override, S5 when-filter, S6 HEAD-mover between verify and publish with legitimate-recheckout positive control, S7 removal) + subset-stage composition control in verify-release.test.mjs. Mutation-verified by the dispatching seat in both directions (true bypass → S1 assertion fires; non-bypass edit → correctly green). Scripts tests 20/20, CI 2490 green. | PR #1305 |
| ✅ Canonical command | `scripts/verify-release.mjs` (stage table pinned to ci.yml by checked-in test). Merged with #1277; now also invokes the RI-N4 evaluator via its `quality-rails` stage (#1308). | `scripts/verify-release.mjs` |
## RI-N2 — Forge + MACP fail-closed (typed explicit simulation)
- ✅ Forge: PR **#1278** merged (head 4917df1f; CI 2477; review 184 fred at pinned head — prior review 172 dismissed by rebase, correctly re-taken).
- ✅ MACP: PR **#1293** merged (head 2097379e; CI 2465; review 173).
- ✅ Post-merge behavior docs: PR **#1299** merged (head 8a405b14; CI 2497; review 186 fargo at pinned head — legitimate independent seat; merged 2026-08-18 with --expect-head pin, content-verified on next @ ff45f7b).
## RI-N3 — PRD authority
- ✅ PR **#1294** merged (head 8d258e1d; CI 2466; review 174).
## RI-N4 — Quality-rails evaluator
- ✅ Probe inventory: PR **#1302** merged (head e06a47fac59; CI 2484; review 187 fargo at pinned head; 54 rows / 21 canonical checks / dispositions 43-2-9-0 row-count-verified; merged 2026-08-18, content-verified on next @ 6435089).
- ✅ TS evaluator absorbs shell probes: PR **#1308** merged (head 68279d61; CI 2506; review 188 fred at pinned head — seven targeted mutations, seven detections, incl. the vacuous-pass hole M1 and stage-removal M7). Evaluator: typed fail-closed verdicts, digested versioned definitions, per-subject sets; QC-19 absorbed (verbatim-list parity oracle), QC-20 as thin adapter (verify.sh unmodified); verify-release `quality-rails` stage wired (RI-N1 consumes the evaluator). Worker-produced, independently verified by the dispatching seat (quality-rails 40/40 incl. sabotage control 6-failed/34-passed restored sha-verified; root build 25/25; typecheck 45/45).
## RI-N5 — Consequence-aware stale UI
- ✅ PR **#1300** merged (head a337d787; CI 2481; review 179). Web suite 199 → 281 tests (failure matrix + negative controls), independently re-run by the dispatching seat before merge.
## Known-open infrastructure item (not a card)
Gateway/ci-base **image** pushes fail on registry credentials: Woodpecker repo
secrets `REGISTRY_USERNAME`/`REGISTRY_PASSWORD` are rejected by the Gitea
container registry (explicit `UNAUTHORIZED` at `/v2/token`; pipeline 2494 after
PR #1306 corrected the secret references — previously masked as an ambiguous
push-permission error since at least 2439). Requires a package-scoped token
(Jason). The npm publish path is green and gated; this item tracks image pushes
only and predates the RI-050 floor.
**Update 2026-08-18 (fargo):** Jason set new secret values ~17:25Z; pipeline
**2507** (the #1308 merge push, first after the update, 18:0xZ) still fails
`build-gateway` with the identical `UNAUTHORIZED`. Read-only isolation (no
secrets read, no CI retries): the registry endpoint and auth mechanism are
HEALTHY — a valid Gitea token via basic-auth mints a JWT at `/v2/token` (200),
bad credentials 401 cleanly. Therefore the failure is isolated to the secret
VALUES, not the endpoint or pipeline. Most likely shape error (labeled guess):
the registry authenticates username + **API token with package scope**, not
username + login password; if REGISTRY_PASSWORD holds a login password rather
than a minted token value, `/v2/token` 401s exactly as observed. npm publishes
remained green in 2507; every publish step except the image push is gated and
green.
**Resolution 2026-08-18 23:47Z — FIXED on the Gitea server (jarvis, #1275
comment 23239).** Root cause was neither scope nor a missing token:
`REGISTRY_USERNAME` held `mosaic`, the **pre-rename org name**. Gitea's rename
redirect covers API/web paths but not Basic-auth username lookup, and
`mosaicstack` is an organization, which has no password — the pair could never
authenticate. Fix: `REGISTRY_USERNAME`=`woodpecker` (the existing service
account, Gitea user 41, already in `ci-publish`) and `REGISTRY_PASSWORD`= a
newly minted `write:package`-only token (`gitea admin user generate-access-token`
in the Gitea container; minting with a token is forbidden server-side). Events
`[push, tag]` preserved. Verified **without a pipeline run**:
`POST /v2/<pkg>/blobs/uploads/` opened then cancelled a session — **202** on
all four kaniko destinations (gateway, appservice, web, ci-base), anonymous
control **401**, wrong-owner control **401**. The earlier "Requires a
package-scoped token (Jason)" expectation is superseded: the defect was a
stale value from the org rename, not a scope grant Jason owed.
**Proof 2026-08-19 ~00:2xZ (fargo): pipeline 2517 green at build-gateway.**
Woodpecker retry of 2512 — identical commit d4d32a8, identical pipeline
config, only the server-side secret changed between runs — went green on
every step (clone, install, verify, build, publish-next-npm,
**build-gateway**). A/B at the same commit isolates the credential as the
variable; the stored value is byte-intact. Retry was serialized (sole run in
flight; merge-purpose CI queue guard had blocked on 2512's terminal failure
at the `next` head, which this retry also clears). The item is closed.
## Process record (audit trail)
- Merges executed under the jarvis principal (topher seat; identity provisioning
pending) via the Gitea API replicating `pr-merge.sh` semantics (head-pin +
squash + keep branch): `pr-merge.sh` hard-codes `main`-only targets and cannot
express this repo's `next` trunk — wrapper gap captured to OpenBrain
(id 9db7a95a) and to the framework queue.
- Reviews tonight: 175/178 (zane's #1298, both heads, by topher); 176/177/179/
180/181/182 (fred) — cross-review rule (producer ≠ reviewer) held on every
merge: producers were pi workers / zane; reviewers were the other seat.
- CI contention note: concurrent PR pipelines on the single CI agent can time
out the web SPA suite (measured 2470/2472 vs serialized 2475/2476/2477);
serialize retries when the queue is busy.
## Process record — 2026-08-18 day takeover (fargo)
- Takeover directive: Jason (via jarvis router + both seats' handoff documents,
relayed verbatim over comms). First-move conflict between the two handoffs
(zane: doctor PR first; topher: review-queue first) resolved on dependency
grounds per jarvis's read — topher's order won; zane's finding-2 doctor PR
(upgraded by fred's measurement) remains queued, nothing depends on it.
- Reviews 186 (#1299) + 187 (#1302): fargo, at pinned heads, as the legitimate
independent seat (topher dispatched both producers; cross-review rule held).
Both merged with --expect-head pinning via the REPO-COPY pr-merge.sh
(allows next; the installed copy still lags — zane's route, not the raw-API
break-glass), each preceded by ci-queue-wait -B next -R mosaicstack/stack.
CI green at both heads (2497, 2484). Merges content-verified on the shipping
ref (TASKS anchors at ff45f7b / 6435089).
- RI-3-002: one pi worker (zai/glm-5.3:high), independently verified by the
dispatching seat before push; PR #1308 reviewed by fred (188, seven
mutations incl. vacuous-pass and stage-removal) and merged head-pinned at
68279d61 → next @ 245e0c4.
- Registry-credential isolation measurement (above) performed read-only; no
secret values read, no retry-pushes against CI.
- One reviewer-scope disclosure (fred, review 188): fred's approval explicitly
did NOT re-run root build/typecheck/mosaic-vitest — those remain the
dispatching seat's numbers. The changed-package suites, verify-release
suite, and seven mutations were fred's own.
@@ -43,8 +43,6 @@ overwritten on upgrade. (Layer model: `constitution/LAYER-MODEL.md`.)
| Secrets / vault usage | `guides/VAULT-SECRETS.md` |
| Tool/credential reference (service CLIs, wrappers) | `guides/TOOLS-REFERENCE.md` |
| Memory protocol (OpenBrain capture/recall) | `guides/MEMORY.md` |
| Seat identity, git credentials, token slots | `guides/SEAT-IDENTITY.md` |
| Reaching another agent (fleet comms) | `guides/FLEET-COMMS.md` |
## Subagent Model Selection (Cost — Hard Rule)
@@ -15,78 +15,8 @@ Merge strategy enforcement (HARD RULE):
- Merge to `main` MUST be squash-only.
- Use `~/.config/mosaic/tools/git/pr-merge.sh -n {PR_NUMBER} -m squash --expect-head {approved_full_sha}` (or PowerShell equivalent).
An estate MAY carry a documented exception for a repository whose gates are commit hooks rather
than review. Such an exception belongs in that estate's own working copy of this guide, is
scoped to the named repository, and is never precedent for a second one.
**Do not use `pr-review.sh` or `issue-comment.sh` to post a verdict** (mosaicstack#1280). Post
through a direct authenticated API call as your own seat, or hand the verdict to the requesting
seat. Handing it over is a legitimate delivery path, not a fallback.
## Evidence Discipline (applies to every finding)
The checklist below says what to look at. This section says when you are allowed to believe what
you saw. Every rule here was earned by a wrong conclusion that reached a report.
1. **A finding is a claim about behavior.** State the failing input, the path taken, and the
wrong result. "This looks fragile" is not a finding.
2. **A green check is not a result until you have shown it could go red.** Run the control. A
`0`, an empty result, or a column of identical values with no failing counterpart is a
non-result.
3. **Measurement and explanation are separate sentences.** Report the command and its output,
then, as its own sentence, what you think it means.
4. **Never widen the case you measured.** If you checked one path, the finding covers one path.
5. **Reproduce a reported failure before recording it, and say which tree you measured.** Two
correct measurements of two different trees disagree without either being wrong.
6. **Verify by content on the ref that ships**, never by ancestry of a local sha. A rebase mints
new shas; a commit being an ancestor of something local proves nothing about the remote.
Compare by digest against `origin/<branch>`.
7. **Confidence is part of the finding.** "I could not reproduce this" is a usable review
comment. A confident guess is not.
8. **Author is not reviewer** (Gate-16). Do not review your own work, or work you shaped closely
enough to be a co-author of. Say so and hand it back.
### Measuring a shell suite
Each of these produced a wrong conclusion before it was written down.
9. **`cmd | tail; echo rc=$?` reports `tail`'s exit code, not `cmd`'s.** It reads as a pass when
the command failed. Redirect to a file and check `rc` directly, or use `${PIPESTATUS[0]}`.
10. **Under `set -o pipefail`, a missed glob makes `ls` exit 2**, the pipeline inherits it, and
`set -e` kills the run. Iterate a glob with a `for` loop and an `-e` test instead of piping
`ls`.
11. **A suite that exits nonzero with ZERO output is an environment question, not a defect in
the code under review.** The usual cause is a sourced dependency that is absent, so `set -e`
kills the first case before anything prints. Extract whole tool trees — `tools/git` alone is
missing `tools/_lib/credentials.sh`. Isolate the variable and prove it by adding only that
back.
12. **`git -C <dir>` in a directory that is not itself a repo answers from the enclosing repo.**
A scratch tree under `~/.mosaic` reports `~/.mosaic`'s HEAD, not the PR's, and every
conclusion drawn from it describes the wrong tree. Confirm `git rev-parse --show-toplevel`
is the tree you think it is before trusting any git output.
### Feedback Categories
- **Blocker**: must fix before merge (security, bugs, test failures)
- **Should Fix**: important but not blocking (code quality, minor issues)
- **Suggestion**: optional improvement (style preference, nice-to-have)
- **Question**: seeking clarification
## Review Checklist
Reviewer seats split this checklist by class rather than duplicating it. A seat reviews its own
sections in full and may raise anything it notices outside them as a Suggestion, never as a
Blocker on someone else's ground.
| Reviewer class | Owns |
| ---------------- | ------------------------------------------------------------------------------------------------------- |
| `rev-code-*` | 1 Correctness, 3 Testing, 4 Code Quality, 4a TypeScript, 5 Documentation, 6 Performance, 7 Dependencies |
| `rev-security-*` | 2 Security, 2a OWASP |
Where two seats of the same class review the same change, they review independently and compare
after. A second seat that reads the first seat's findings before measuring is a proofreader, not
a second opinion.
### 1. Correctness
- [ ] Code does what the issue/PR description says
@@ -123,7 +53,7 @@ a second opinion.
- [ ] Tests cover happy path AND error cases
- [ ] Situational tests cover all impacted change surfaces (primary gate)
- [ ] Tests validate required behavior/outcomes, not only internal implementation details
- [ ] TDD was applied when required by `guides/QA-TESTING.md`
- [ ] TDD was applied when required by `~/.config/mosaic/guides/QA-TESTING.md`
- [ ] Coverage meets 85% minimum
- [ ] Tests are readable and maintainable
- [ ] No flaky tests introduced
@@ -152,7 +82,7 @@ a second opinion.
### 5. Documentation
- [ ] Complex logic has explanatory comments
- [ ] Required docs updated per `guides/DOCUMENTATION.md`
- [ ] Required docs updated per `~/.config/mosaic/guides/DOCUMENTATION.md`
- [ ] Public APIs are documented
- [ ] Private/internal APIs are documented
- [ ] API input/output schemas are documented
@@ -196,6 +126,13 @@ git diff main...HEAD
- Distinguish between blocking issues and suggestions
- Be constructive, not critical of the person
### Feedback Categories
- **Blocker**: Must fix before merge (security, bugs, test failures)
- **Should Fix**: Important but not blocking (code quality, minor issues)
- **Suggestion**: Optional improvements (style preferences, nice-to-haves)
- **Question**: Seeking clarification
### Review Comment Format
```
@@ -1,86 +0,0 @@
# Fleet Comms Guide
How one seat reaches another on a host. The mechanism is the framework's; the sessions and
sockets are per-host, so measure yours rather than trusting an example.
`mosaic <runtime>` would normally inject the addressing block from the roster. Where the composer
is unavailable, or where the roster is stale, this guide is the substitute.
## Measure the fleet; do not trust the roster
`fleet/roster.yaml` is a declaration of intent, not an observation. It routinely names a socket
that was never created, lists seats that are not running, and omits seats that are — this was
all three have been observed true at once on a live host. Find out what is actually
up before addressing anyone:
```bash
tmux list-sessions
tmux list-panes -a -F '#{session_name} #{pane_current_command} #{pane_current_path}'
```
The pane command tells you the runtime. A pane showing `bash` is an idle shell with no agent
attached — a send there lands in a shell prompt and is not read by anyone.
Use the **default socket**. Do not pass `-L mosaic-fleet` on the strength of the roster.
## Sending
```bash
~/.config/mosaic/tools/tmux/agent-send.sh -s <dst_session> -C <class> -m "<message>"
```
`-s` also accepts `session:window.pane`. `-f <file>` sends a file body; stdin works too.
### Classes
`-C` takes exactly one of these. Anything else exits 3.
| Class | Use for |
| -------------- | -------------------------------------------------------- |
| `terminal-log` | log only; never needs the agent's attention |
| `actionable` | a decision, blocker, gate, or question needing an answer |
| `human` | relayed from a human operator |
| `reaction` | an ack or acknowledgement token |
| `digest` | machine wake, coalescible |
An absent class is treated as `actionable` by consumers, which is the fail-safe direction. Prefer
naming it anyway.
### Addressing preamble
The wire format is `[<src> -> <dst> class=<class>] <body>`. Flip it when you reply — the tool
sends, it does not auto-reply.
### Exit codes
| rc | Meaning |
| --- | ---------------------------------------------- |
| 0 | delivered or queued |
| 1 | target session not found |
| 2 | text reached the pane but is **still a draft** |
| 3 | usage error (bad class, missing `-s`) |
**Never retry on rc=2.** The message is in the target pane; retrying double-sends it. Confirm
instead:
```bash
tmux capture-pane -p -t <session>:0.0 | tail -20
```
rc=2 is the normal result when the target is an idle pi seat.
## Durable comms
tmux delivery is host-local and does not survive a pane. Anything that must outlive the session
goes through the estate's durable comms protocol — a committed `comms/` tree in an estate repo,
with its own README. Use it for cross-host messages, verdicts, and anything a later session needs
to find.
## Handing work across seats
1. **A verdict handed to the requesting seat is a legitimate delivery path**, and the required one
for anything `pr-review.sh` would otherwise post (see `guides/CODE-REVIEW.md`).
2. **Address the seat, not the runtime.** A seat name is a session name; whether it runs claude,
pi or codex is not the sender's business.
3. **Say what you measured, not just what you concluded** — the receiving seat cannot see your
terminal.
@@ -1,133 +0,0 @@
# Seat Identity & Credentials Guide
Every agent that touches a Mosaic-managed git host acts as a named seat with its own credential.
This guide is how that works on a host, and what an agent must never do with it.
The mechanism below is the framework's. The specific paths, seats and stores are per-host:
measure yours before trusting any of them.
## The rule
**One seat, one identity, one token file.** A seat never borrows another seat's credential, never
falls back to a shared owner account, and never carries a second copy of its own token. A second
copy is drift, and drift surfaces as the stale copy returning 401 — which reads as a revoked
token and sends whoever debugs it somewhere else entirely.
A credential refusal is correct behavior, not a bug to route around. If git refuses with a
fail-closed diagnostic, the fix is to provision or correct _your_ identity. Escalate; do not
substitute.
## How a credential is resolved
Find the helper the way **git** does, not with `command -v`. Git runs whatever
`credential.helper` names, and on a Mosaic host that is an absolute path — so a PATH lookup
answers a different question and the two disagree the moment the PATH copy is removed. It was
removed on hosts that have completed that migration.
```bash
git config --get-all credential.helper # every helper, in the order git tries them
```
Git tries **each** configured helper in turn until one supplies a credential. A fail-closed
helper supplies nothing, so a second helper configured behind it silently becomes the one that
answers. When you care which binary serves a credential, read the whole list.
Resolve all three forms git accepts — absolute path, `!command`, and a bare name looked up on
PATH — not just the one your host happens to use.
The helper resolves the identity in this order:
1. `$MOSAIC_GIT_IDENTITY`
2. `git config --get mosaic.gitIdentity`
3. the username git supplied on stdin
It maps the host to a store prefix — `git.mosaicstack.dev` to `gitea-mosaicstack`,
`git.uscllc.com` to `gitea-usc`. Any other host is declined quietly with rc=0, which is not an
error and raises no escalation.
Then it chooses **one** of two stores, and reads exactly one file:
```
brain_home = ${MOSAIC_BRAIN_HOME:-$HOME/.mosaic}
seat — when $brain_home/fleet/agents/<identity>/ EXISTS
$brain_home/fleet/agents/<identity>/secrets/<prefix>-<identity>.token
service — otherwise
~/.config/mosaic/secrets/gitea-tokens/<prefix>-<identity>.token
```
**There is no precedence between the two and no fallback from one to the other.** The existence
of the seat directory decides it. A seat that has a directory and an empty slot fails closed; it
does not reach the service store. That is the intended behavior — the alternative is an agent
silently acting as somebody else.
If the file is unreadable the helper **fails closed**: it refuses and writes a durable record to
the escalation spool. It does not fall back to a shared account. The record is what exists — any
alerting built on top of it is a separate, best-effort concern and is not performed by the helper,
so do not wait for a notification that nothing sends. That fallback is what made
`usc/uconnect#3084` unattributable, and it was removed deliberately.
Verify the helper you actually have:
```bash
h=$(git config --get credential.helper)
grep -c 'FAIL CLOSED' "$h" # expect >= 1
grep -c 'fleet/agents' "$h" # expect >= 1; 0 means it predates mosaicstack#1311
```
## Where a seat's token lives
The seat slot is the **only** copy:
```
~/.mosaic/fleet/agents/<seat>/secrets/<prefix>-<seat>.token real file, mode 600
```
The framework store at `~/.config/mosaic/secrets/gitea-tokens/` holds tokens for **service
identities only** — identities with no seat directory. A seat's token does not belong there.
Before mosaicstack#1311 the deployed helper knew only the service store, and seats were bridged
with a symlink from the store into the slot. **Those bridges must be removed once a seat-aware helper is deployed, and must not be
recreated.** Remove them only after the helper can reach the slot without them; the reverse order
takes every seat offline. A symlink
is not how a system finds a credential; the helper resolving the right store is.
`.principal` and `.scopes` beside the token are grant records, not secrets. They are tracked. The
`.token` never is.
### Provisioning a new seat
1. Create `~/.mosaic/fleet/agents/<seat>/secrets/` mode 700.
2. Write `.principal` (the Gitea login) and `.scopes` (the granted scopes), mode 600.
3. The estate operator mints the token into the seat slot, mode 600. Agents do not mint their
own, and do not ask another agent to mint one for them.
4. Verify with an authenticated `GET /user` and confirm the returned login is the seat, **not the
minting account**. Record the date in `ENTITY.md`. Never record the value.
There is no step that links the framework store to the slot. A seat-aware helper reads the slot
directly; a store entry pointing at a slot is the bridge described in **Where a seat's token lives** above,
and it is not part of provisioning.
Until step 3, the seat is unminted and its git writes fail closed. That is the designed state and
is safe to launch in — the seat is told at launch so it does not discover it mid-task.
## Acting as yourself
Name the identity on every invocation:
```bash
MOSAIC_GIT_IDENTITY=<seat> git push
git -c user.name=<seat> -c user.email=<seat>@mosaicstack.dev commit -m "..."
```
**Never persist `git config mosaic.gitIdentity` inside a `~/src/stack` worktree.** Every worktree
of that clone shares one `.git/config`, so a persisted identity there silently rewrites the
identity of every other seat working in that clone. The per-invocation form has no exception.
## Handling
1. **Never print a token value.** Compare by SHA-256 digest, or write `<REDACTED>`.
2. **Never stage a `.token`, `secrets.json`, or `ENTITY.md`.** Stage explicit paths and **never
`git add -A`** — `secrets/*.principal` and `secrets/*.scopes` are covered by no ignore rule.
3. **Never place a token in an environment variable** in an interactive session. A `declare -x`
dump has leaked the whole environment to a terminal before.
4. **No real credential or operator data on a sandbox VM, ever.**
@@ -15,5 +15,3 @@
| Infrastructure/DevOps | `~/.config/mosaic/guides/INFRASTRUCTURE.md` |
| QA/Testing | `~/.config/mosaic/guides/QA-TESTING.md` |
| Secrets management (Vault) | `~/.config/mosaic/guides/VAULT-SECRETS.md` |
| Seat identity / git credentials | `~/.config/mosaic/guides/SEAT-IDENTITY.md` |
| Reaching another agent (fleet comms) | `~/.config/mosaic/guides/FLEET-COMMS.md` |