13 KiB
#1043 — Fleet pane git-identity propagation
Objective
Ensure a fleet seat's launched runtime process receives its roster-derived MOSAIC_GIT_IDENTITY, and lock the complete generated-environment propagation boundary with an enumerated set comparison.
Tracking
- External issue:
mosaicstack/stack#1043 - Branch:
fix/1043-pane-git-identity - Coordinator:
tl-mosaic docs/TASKS.md: read-only by project worker contract; not modified.
Constraints
- RED-first bug reproducer is mandatory.
- R7 delete-the-subject mutation must turn the behavioral test red.
- Assert launched-process environment, not source text.
- One push only; do not poll CI after push.
- Run the CI queue guard immediately before push and report its
state=line as state, not evidence. - Do not modify a live host launcher or obtain/copy another credential.
- Self-post the PR, verify provider attribution, then stop.
- Final status wording:
believed-fixed, pending jarvis validation.
Scope inventory
Re-derived against origin/main at 85d2108e:
- Launch consumer:
packages/mosaic/framework/tools/fleet/start-agent-session.sh - Behavioral launch test:
packages/mosaic/framework/tools/fleet/test-start-agent-session.sh - Generated-environment contract/parser:
packages/mosaic/src/fleet/generated-env-boundary.ts - Roster projection producers:
packages/mosaic/src/commands/fleet.tspackages/mosaic/src/fleet/fleet-reconciler.tspackages/mosaic/src/fleet/fleet-agent-crud.tspackages/mosaic/src/fleet/v1-v2-migration.ts
- Contract and producer tests discovered by repository search.
- Generated-environment operator/developer docs and their executable documentation contract test.
Discrepancy sent to tl-mosaic: current main no longer contains the charter's PANE_SHELL_SNIPPET; #772 replaced it with an /usr/bin/env -i argv launch boundary, and current generated projections do not declare git identity. Code-read inventory is NOT MEASURED behavior.
Plan
- Add the process-environment set-comparison regression first and record RED.
- Add roster-derived
MOSAIC_GIT_IDENTITY=<agent name>to the complete generated projection contract. - Validate identity syntax and equality with
MOSAIC_AGENT_NAME; pass it through the clean pane environment. - Update affected projection tests and generated-environment docs.
- Run focused and baseline gates.
- Perform R7 by deleting the pane propagation entry, prove RED, restore, and prove GREEN.
- Run independent review, remediate, commit, queue guard, one push, self-post PR, verify provider attribution, and stop without CI polling.
Budget
No explicit token cap was provided. Working cap: one narrow logical unit, no dependency installation unless existing tooling requires it, no unrelated refactor.
Evidence log
TDD and mutation evidence
- RED-first, repository launcher:
bash packages/mosaic/framework/tools/fleet/test-start-agent-session.shexited 64 on pre-fix source withcode=unknown-key key=MOSAIC_GIT_IDENTITY. The generated seat could not launch with the required declared identity. - GREEN: the same repository launcher test emitted
ok - start-agent-session generated environment boundary. - R7 delete-the-subject: removed only
"MOSAIC_GIT_IDENTITY=$MOSAIC_GIT_IDENTITY"from the repository launch array; the same test exited 1 withFAIL: runtime pane omitted or changed generated environment keys: MOSAIC_GIT_IDENTITY. - R7 restoration: restored that launch entry; the same test returned green.
- Launcher under test is explicitly
packages/mosaic/framework/tools/fleet/start-agent-session.shthrough the test's$START, not the stale installed host copy.
Situational and focused tests
- Repository launcher boundary: green, including set comparison of all nine generated projection entries and fail-before-tmux cases for missing, unsafe, mismatched, and local-shadow Git identity.
- Fleet systemd launcher integration:
bash packages/mosaic/framework/systemd/user/test-fleet-units.sh— green. - Focused Mosaic Vitest set: 6 files, 311 tests — green.
bash -non changed shell files — green.git diff --check— green.
Baseline gates
pnpm typecheck— 45/45 tasks green.pnpm lint— 25/25 tasks green.pnpm format:check— green.pnpm test:checkout— green.- Repository-wide Vitest under a hermetic current-version npm prefix: Mosaic 81/81 files and 1510/1510 tests green; other workspace test tasks shown green before the framework-shell phase.
- Canonical
pnpm testis not fully green on this host for unrelated environment-sensitive gates:- the first two runs exposed the globally installed Mosaic 0.0.48 update banner in three CLI smoke tests expecting empty stderr;
- after isolating that global-version input, the framework wake assertion aborted at the known
#973BashBASH_LINENOconvention check (exit 97; observed[3 5], expected[3 4]). No tests were weakened or bypassed; focused changed-surface tests are green. CI remains the canonical clean-environment result and is intentionally not polled after push per charter.
Independent review
- Codex code review first pass: request changes for missing shell rejection-path coverage.
- Remediation: added table-driven missing/unsafe/mismatch/local-shadow launcher cases, each asserting no tmux call.
- Codex code re-review: approve, no findings, confidence 0.88.
- Codex security review: risk
none, no findings, confidence 0.97.
Acceptance criteria mapping
| Acceptance criterion | Evidence |
|---|---|
| AC-FGI-01: launched process receives every generated key/value | Repository launcher process-environment comm -23 set comparison; GREEN and R7 RED evidence above |
| AC-FGI-02: missing, unsafe, or split identity fails before tmux | Table-driven shell cases plus TypeScript generated-boundary tests |
| AC-FGI-03: focused/baseline/review evidence recorded | Commands and review outcomes above; host-sensitive full-suite limitations stated explicitly |
Documentation checklist
- PRD updated with #1043 requirements and acceptance criteria.
- Fleet launch runbook, generated-env concept, and generated-env reference updated.
- No API/OpenAPI, sitemap, user publishing target, deployment, or external docs publication change applies.
docs/TASKS.mdremains unmodified per its single-writer project contract.
Round 2 — PR #1073 review 97 remediation
Review blocker
The launched-process suite was signed-excluded from CI enumeration. Manual GREEN/R7 evidence therefore did not prove a PR workflow could detect regression.
RED-first and canonical wiring
- Removed the suite's signed exclusion before adding a CI execution path.
check-test-enumeration.shwent RED with exactUNENUMERATEDoutput fortest-start-agent-session.sh: population 49, enumerated 30, excluded 18.- Added both
framework/tools/fleet/test-start-agent-session.shandframework/systemd/user/test-fleet-units.shto@mosaicstack/mosaic's canonicaltest:framework-shellchain. - The guard returned GREEN: population 49, enumerated 32, excluded 18, surfaces 45. The systemd suite is outside the guard's tools-only population but now has the same explicit canonical execution disposition.
Workflow-level R7
- Deleted only the pane launch entry
"MOSAIC_GIT_IDENTITY=$MOSAIC_GIT_IDENTITY". - Ran the exact
.woodpecker/ci.ymltest-step command,pnpm test, with only a temporary PATH-scoped npm shim reporting the checkout's current 0.0.49 version so the unrelated global 0.0.48 banner could not preempt the shell chain. - Result: exit 1 at
@mosaicstack/mosaic#test, with the enumeration guard GREEN followed byFAIL: runtime pane omitted or changed generated environment keys: MOSAIC_GIT_IDENTITY. - Restored the launch entry. The canonical
test:framework-shellchain then reached both newly wired suites and printed both GREEN markers before the known unrelated #973 host-onlyBASH_LINENOabort. - An actual provider PR workflow on the intentionally broken mutant is NOT MEASURED: the one-push constraint forbids pushing a red mutant and then a repaired head. Local execution proves the exact PR workflow command and dependency chain go RED on the subject deletion; CI on the repaired pushed head remains canonical.
Workflow population
- DEFINED: 3 workflows (
ci.yml,ci-image.yml,publish.yml). - ELIGIBLE for
pull_request: 1/3 (ci.yml), based on top-levelwhen:clauses. - REPORTED: Round-1 exact-head provider read reported 1/1 eligible context (
ci/woodpecker/pr/ci). Post-remediation-head reported count is NOT MEASURED by this seat because CI polling is prohibited; workflow definitions and eligibility did not change.
Independent remediation review
- First Round-2 review identified a CI-image blocker: the newly wired launcher suite used Perl, which the Alpine CI base does not install.
- Replaced the suite's three Perl-only fixture mutations with POSIX/BusyBox-compatible
sed -isubstitutions; production behavior and assertions are unchanged. - Codex re-review: APPROVE, confidence 0.93, no findings.
Vitest denominator reconciliation
The PR's 311/311 is correct for its explicitly named six-file command at both the original and remediation worktrees:
- generated environment boundary: 24
- fleet documentation: 23
- Tess service profile: 6
- fleet regen command: 27
- fleet agent CRUD command: 22
- fleet command: 209
- total: 311
Review 97 reported 312/312 without naming its six files. That is a different or miscounted population and cannot replace the command-scoped 311 denominator; the PR follow-up will name the exact files and arithmetic.
Round 3 — Alpine stale-marker portability
Objective and plan
- Replace the GNU-only relative-date fixture with a deterministic POSIX/BusyBox timestamp while preserving the required stale-marker assertion.
- Re-run the launcher suite in the canonical
ci-base:latestAlpine image, then run applicable repository gates and independent review. - Update the PR body to name the repeated GNU-host/Alpine-CI portability pattern, run the mandatory queue guard, push once, verify provider attribution, and stop without CI polling.
- Working budget: 8K tokens; scope is one fixture line plus delivery evidence. No production behavior changes.
RED-first evidence
Before the fix, the canonical CI image command
docker run --rm -v "$PWD:/work" -w /work git.mosaicstack.dev/mosaicstack/stack/ci-base:latest bash packages/mosaic/framework/tools/fleet/test-start-agent-session.sh
exited 1 at the stale-marker setup with exact BusyBox output
touch: invalid date '10 seconds ago'. The prior fresh-marker assertions had already executed, matching pipeline 2233's failure location.
Root cause and fix
The test used GNU touch -d relative-date parsing although the PR workflow runs on Alpine/BusyBox. The fixture now uses POSIX touch -t 200001010000.00, a fixed timestamp that is unconditionally stale; the stale assertion remains mandatory and was not made tolerant of missing timestamp metadata.
Structural pattern
This is the third GNU-host/Alpine-CI portability defect in the lane: GNU grep multi-match counting, Perl-only fixture mutation, and GNU touch -d date parsing. The repeated cause is shell suites authored on a GNU host but executed in an Alpine CI image; durable prevention belongs in CI-image execution or portability lint, not assertion weakening.
GREEN and quality evidence
- Focused launcher suite in
ci-base:latest: exit 0,ok - start-agent-session generated environment boundary. - Canonical test step in
ci-base:latestwith the pipeline'spgvector/pgvector:pg17service, readiness check, migration, andpnpm test: exit 0; 46/46 Turbo tasks; Mosaic 81/81 files and 1510/1510 tests; Gateway 57 passed/5 skipped files and 629 passed/11 skipped tests; enumeration 49 population / 32 enumerated / 18 signed exclusions / 45 named surfaces. - The first image-only
pnpm testattempt lacked the pipeline PostgreSQL service and failed only on connection refusal after the launcher suite was GREEN. The rerun supplied the canonical service precondition and passed. - Canonical-image baseline: typecheck 45/45 tasks, lint 25/25 tasks, format check GREEN;
git diff --checkGREEN. - Independent Codex code review: APPROVE, confidence 0.96, 2/2 Round-3 files, no findings.
- Independent Codex security review: risk none, confidence 0.99, 2/2 Round-3 files, no findings.
Re-derived inventory and denominators
- Round-3 git delta: 2/2 files — launcher suite and task scratchpad; 25 insertions / 1 deletion before evidence finalization.
- Full PR path inventory against
origin/mainat85d2108e: 19/19 changed paths; Round 3 adds no new PR path. - Workflow definition population: 1/3 pull-request-eligible (
ci.ymlofci.yml,ci-image.yml,publish.yml). - Do not re-litigate the settled 311/312 populations; both are valid for their separately named Tess6 and CRUD-core7 sets.
Residual risk
- Landing on
maindoes not update the currently installed host launcher. Host framework installation/reseed and Jarvis live-seat validation are separate downstream events. - Canonical CI result is pending and will not be polled by this seat.