Commit Graph
33 Commits
Author SHA1 Message Date
Mos f214613680 test(tools/git): stop the fail-closed test escaping its sandbox; cover the API path
ci/woodpecker/pr/ci Pipeline was successful
rev-974 (#1085 review 130) found three blockers. This closes the first two.

[1] SANDBOX ESCAPE. The test ran under `set -uo pipefail` with unchecked mkdir,
    calls-log redirect and `cd "$REPO_DIR"`, then prepended a possibly-nonexistent
    $MOCK_BIN to PATH -- while `git remote add origin` names the REAL repository.
    rev-974 forced setup failure with an unwritable AGENT_WORK_ROOT and the test
    continued past every error, ran `git init` in its CALLER's directory, added the
    real origin, and invoked its target:

        TARGET_REACHED args=-i 42 -c closing note

    With the committed target that is the real, provider-mutating issue-close.sh.
    ShellCheck flagged the unguarded cd as SC2164 independently.

    Now: `set -euo pipefail`, every setup step checked with a legible reason, and
    assert_mocked() proves BOTH `tea` and `curl` resolve inside $MOCK_BIN before any
    target invocation. Control: unwritable AGENT_WORK_ROOT -> rc=1 at mkdir, target
    never reached.

[2] THE API/no-login BRANCH HAD NO DISCRIMINATING COVERAGE. The mock always returned
    a tea login, so `gitea_issue_comment_api || fail-closed` was never executed.
    rev-974 replaced the whole fallback contract with an unconditional close --
    silently dropping the comment -- and the committed test still passed rc=0.

    Added three cases asserting the POSTCONDITION (which HTTP calls happened, in what
    order) rather than that a command ran: comment POST fails -> no PATCH and non-zero;
    comment succeeds -> strictly POST,PATCH; no comment requested -> PATCH only, never
    a POST. The curl mock now records method and URL. Control: replaying rev-974's
    contract destruction now fails with "API path: no comment POST attempted".

Two self-inflicted traps hit while adding `set -e`, both the same family as the #1086
defect be-coder-08 found, and both silent:
  - `grep -q X "$CALLS" && fail "..."` -- the ABSENT case (grep rc=1, the PASSING case
    for a must-not-appear assertion) is the last command of an && list and terminates
    the script with no message. All four converted to if-blocks.
  - `run_target ...; rc=$?` -- the function's non-zero RETURN trips set -e in the CALLER
    before rc is read; run_target's internal `set +e` protects the target, not the
    caller. All five call sites now `rc=0; run_target ... || rc=$?`.

Controls:
  unchanged main                  -> rc=1 "used 'tea issue comment'"
  fallback contract destroyed     -> rc=1 "API path: no comment POST attempted"
  unwritable AGENT_WORK_ROOT      -> rc=1 at setup, target never invoked
  fixed source                    -> rc=0

[3] remains open: with MOSAIC_GIT_IDENTITY=rev-974 the wrapper resolves
    GITEA_LOGIN_NAME=mosaicstack-mos, so one principal holds but the operation is
    attributed to Mos rather than the requested seat. That changes identity resolution
    shared by every wrapper in this directory and is not folded in here.

Reported-by: rev-974
2026-08-07 00:33:57 -05:00
549b6fbaae fix(tools/git): use tea comment, keep one principal, add a red-first regression
Addresses both blockers from review 127 (rev-security-02) and corrects the
severity claim in the original report.

Blocker 1 -- mixed principals. Routing the comment through the token-
authenticated gitea_issue_comment_api() attributed the comment to the token
holder while the close still used --login $GITEA_LOGIN_NAME: two principals for
one operation. `tea comment` accepts the same --repo/--login flags, so the tea
branch now uses it and both calls carry the same principal. The no-login branch
keeps the API helper for both, also a single principal.

Blocker 2 -- no regression test. Adds test-issue-close-fail-closed.sh on the
existing mocked-tea/sandboxed-git harness pattern. Asserts: a failed comment
does not close the issue and exits non-zero; a successful comment does close it;
the subcommand is top-level `tea comment`, never `tea issue comment`; and the
comment and close carry the same --login. GREEN on this branch, RED on main.

Severity correction. The original report said the issue closes anyway and the
audit trail is silently lost. It does not: set -e at line 5 aborts the script
when the comment fails, so the close is never reached. The real defect is that
issue-close.sh -c cannot succeed at all where a tea login resolves -- loud, not
silent. The explicit || guard is retained deliberately: a fail-closed property
that depends on set -e disappears the moment anyone adds `|| true` or wraps the
call in a conditional. Posted as a comment on #1081 and #1085.

Refs #1081

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Amf1Neca162odgcbCWMk1y
2026-08-07 00:33:57 -05:00
5d342f77af fix(tools/git): issue-close.sh silently dropped the closing comment
`tea issue comment` is not a subcommand -- tea 0.11.x exposes only
list/create/edit/reopen/close under `tea issue`, and comments are the
top-level `tea comment`. The call therefore always failed. Its result was
never checked, so the script went on to `tea issue close`, which IS valid:
the issue closed and the record of why it closed was silently lost.

Route the comment through the existing gitea_issue_comment_api() helper on
both branches. It is login-independent and was already the mechanism used by
the no-login fallback. Both call sites now fail closed: if the comment cannot
be posted, the issue is not closed.

Verified behaviourally against the live provider, both directions:
  negative -- comment cannot post => "NOT closing (fail closed)", exit 1,
              issue left open
  positive -- comment posts and issue closes => state=closed, comments=1, exit 0

Refs #1081

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Amf1Neca162odgcbCWMk1y
2026-08-07 00:33:57 -05:00
Mos f744f32214 feat(tools/git): explain tea's misleading user does not exist error (stale token, not a missing account) (#1086)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-08-07 05:07:40 +00:00
Mos 8ff7aac0ca fix(tools/git): detect-platform died silently outside a repo, taking every wrapper with it (#1089)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-08-07 04:26:36 +00:00
be-coder-08andMos 80a45b1e1c feat(pr-merge): preserve linked authors in squash messages (#1066)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: be-coder-08 <[email protected]>
2026-08-06 05:36:59 +00:00
be-coder-08andMos 16f91157a1 test(ci): make queue guard harness deterministic (#1062)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: be-coder-08 <[email protected]>
2026-08-05 21:49:44 +00:00
coder-mos1andmos-dt-0 58b971aba3 fix(rm-03): make CI queue guard fail on asserted non-readiness (#1032)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: coder-mos1 <[email protected]>
2026-08-01 18:55:26 +00:00
mos-dt-0andMos 826a8b3b26 fix(git): pr-review.sh — surface the provider's stated reason, drop the hardcoded #865 attribution (#1006)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: mos-dt-0 <[email protected]>
2026-07-31 10:52:58 +00:00
Mos 089615f63b feat(git): push-guard — refuse verifications satisfied by the null case (closes #975) (#974)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-31 03:35:24 +00:00
jason.woltjeandMos 2483dada33 fix(framework): pr-review.sh -r/--repo + -H/--host overrides + UA + repo preflight (Patches 5/5c) (#896)
ci/woodpecker/push/publish Pipeline was canceled
ci/woodpecker/push/ci Pipeline was canceled
Co-authored-by: jason.woltje <[email protected]>
Co-committed-by: jason.woltje <[email protected]>
2026-07-25 22:08:08 +00:00
jason.woltjeandMos 3c7890f17f fix(framework): detect-platform get_gitea_token fail-loud on absent per-slot token (Patch 2b) (#890)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: jason.woltje <[email protected]>
Co-committed-by: jason.woltje <[email protected]>
2026-07-25 20:51:19 +00:00
jason.woltjeandMos 4422231bdb feat: per-agent Gitea identity resolution (#873)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
Closes #873

Mos (id-11) Gate-16 merge: independent APPROVE @4b472a22 (author-blocker dissolved via (a) re-author, identical tree hash to tech-approved head), author id2 != approver id11, clean mosaic-coder commit-author, CI green wp1985. Framework train COMPLETE 6/6.

Co-authored-by: jason.woltje <[email protected]>
Co-committed-by: jason.woltje <[email protected]>
2026-07-23 18:09:34 +00:00
jason.woltjeandMos 8504216964 fix(pr-review): case-insensitive _belongs slug compare (#875)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
Closes #875

Mos (id-11) Gate-16 merge: independent APPROVE @9d8d58ae, author id2 != approver id11, clean mosaic-coder commit-author, CI green wp1982.

Co-authored-by: jason.woltje <[email protected]>
Co-committed-by: jason.woltje <[email protected]>
2026-07-23 17:53:26 +00:00
jason.woltjeandMos 7edc9b3121 fix(gitea): direct REST comment/review with fail-closed read-back (#865)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
Closes #865

Mos (id-11) Gate-16 merge: fresh confirmatory independent APPROVE @8ac7e70f (1241-case fuzz 0 fail-open), author id2 != approver id11, clean commit-author, CI green wp1966.

Co-authored-by: jason.woltje <[email protected]>
Co-committed-by: jason.woltje <[email protected]>
2026-07-23 17:25:32 +00:00
jason.woltjeandMos 48fd1df28a fix(ci-queue-wait): treat absent branch (404) as queue-clear (#872)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was canceled
Closes #872

Mos (id-11) Gate-16 merge: independent review APPROVE @23cbdaf8, author jason.woltje(id2) != approver Mos(id11), CI green wp1974.

Co-authored-by: jason.woltje <[email protected]>
Co-committed-by: jason.woltje <[email protected]>
2026-07-23 17:08:57 +00:00
jason.woltje 344d86a635 fix(#812 follow-up): normalize detect-platform.sh host-match port comparison by scheme (#859)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-20 10:13:29 +00:00
jason.woltje 3b70c66c07 fix(framework): drop unsupported --comment from tea pr approve/reject; route review body via durable comment (#835) (#857)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-20 09:19:48 +00:00
jason.woltje aa999daf1b fix(framework): durable Gitea comment posting in pr-review.sh via REST + read-back verify (#812) (#852)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-20 06:45:48 +00:00
jason.woltje b580d37d51 Fixes #703 (#705)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline failed
2026-07-12 20:49:43 +00:00
jason.woltje a99aded26d fix(tools/git): -h/--help now exits 0 across 7 wrappers (#702)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-11 09:23:46 +00:00
jason.woltje 4df38f7e81 fix(tools/_lib): /etc/mosaic host-level fallback for credential resolution (#700)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-10 01:57:12 +00:00
jason.woltje e6b53ea103 fix(tools): default AGENT_WORK_ROOT to $HOME/mosaic/agent-work (#641)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was canceled
2026-06-23 13:40:13 +00:00
jason.woltje bf24066a49 feat(framework): P1+P2 — public sanitization + blocking CI gate (#572)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-06-21 02:40:11 +00:00
jason.woltje 92316ab41e feat(framework): P0 — MIT license + executable-leak sanitization (#570)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-06-21 01:43:49 +00:00
jason.woltje 57919c38d8 fix(framework/tools): wrapper hardening — TLS validation, cred-path fallback, no-CI fast-exit (#551)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-06-20 10:16:38 +00:00
jason.woltje ab4e138003 feat(framework/tools): orchestration helpers — lane-brief.sh + ci-wait.sh (#547)
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/push/publish Pipeline was canceled
2026-06-18 22:08:40 +00:00
jason.woltje 719c6ac3db fix(framework/tools): eval injection, broken JSON, tmpfile leak (#549)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was canceled
2026-06-18 21:35:32 +00:00
jason.woltje 98a771c8f8 Fix Gitea wrapper login resolution (#538)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-06-12 02:34:18 +00:00
jason.woltje dde95a59b3 fix(pi): reduce startup skill-token overhead (#527)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-06-05 18:36:42 +00:00
jason.woltje 821e19dcbb fix(mosaic-tools): roll up Gitea and Woodpecker wrapper fixes (#524)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-05-26 20:56:09 +00:00
jason.woltje 2e31626f87 fix: simplify updater to @mosaic/mosaic only, add explicit tea repo/login flags (#388)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-05 02:09:23 +00:00
Jason Woltje b38cfac760 feat: integrate framework files into monorepo under packages/mosaic/framework/
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
Moves all Mosaic framework runtime files from the separate bootstrap repo
into the monorepo as canonical source. The @mosaic/mosaic npm package now
ships the complete framework — bin scripts, runtime configs, tools, and
templates — enabling standalone installation via npm install.

Structure:
  packages/mosaic/framework/
  ├── bin/          28 CLI scripts (mosaic, mosaic-doctor, mosaic-sync-skills, etc.)
  ├── runtime/      Runtime adapters (claude, codex, opencode, pi, mcp)
  ├── tools/        Shell tooling (git, prdy, orchestrator, quality, etc.)
  ├── templates/    Agent and repo templates
  ├── defaults/     Default identity files (AGENTS.md, STANDARDS.md, SOUL.md, etc.)
  ├── install.sh    Legacy bash installer
  └── remote-install.sh  One-liner remote installer

Key files with Pi support and recent fixes:
- bin/mosaic: launch_pi() with skills-local loop
- bin/mosaic-doctor: --fix auto-wiring for all 4 harnesses
- bin/mosaic-sync-skills: Pi as 4th link target, symlink-aware find
- bin/mosaic-link-runtime-assets: Pi settings.json patching
- bin/mosaic-migrate-local-skills: Pi skill roots, symlink find
- runtime/pi/RUNTIME.md + mosaic-extension.ts

Package ships 251 framework files in the npm tarball (278KB compressed).
2026-04-01 21:19:21 -05:00