Compare commits

..
1045 Commits
Author SHA1 Message Date
jason.woltje 50d2a2eba9 Record independent verification and completion of skill repair (#1498) 2026-09-08 18:13:46 -05:00
jason.woltje f3dce32088 Repair native launcher skill rename and fail-closed regression coverage (#1498) 2026-09-08 18:12:20 -05:00
jason.woltje 12ff5da7df Record owner acceptance and close publication recovery trial (#1497) 2026-09-08 17:57:29 -05:00
jason.woltje 10448e41a2 Record verified publication and owner acceptance handoff (#1497) 2026-09-08 17:20:12 -05:00
jason.woltje 29c1defe29 Publish reviewed development agents and WUI draft with recovery evidence (#1497) 2026-09-08 17:15:03 -05:00
jason.woltje 3b7fd19d08 docs: verify published wave and set registry review next 2026-09-08 12:44:13 -05:00
jason.woltje 69f10a4062 fix(tmux): explicit transport-only dispatch and safe remote quoting (#1496) 2026-09-08 12:41:25 -05:00
jason.woltje 67eaf6fb47 docs(logs): pending session/build records through 2026-09-07
Append-only BUILD-LOG phases, SESSIONS registrations, and CURRENT
checkpoint state accumulated through the consolidation and inspector
review waves.
2026-09-07 14:07:16 -05:00
jason.woltje 3ea385223e feat(skills): six new ms-* skills
ms-archify (evidence-based architectural mapping), ms-sdlc,
ms-proactive-agent, ms-goal, ms-grill-me, ms-frontend-design.
2026-09-07 14:07:16 -05:00
jason.woltje 193479b52d docs: concept annexation, provider/reference docs, ACT-1 groundwork
Mosaic concepts pages now own the adapted content; source/license
metadata under docs/reference/concepts. Adds ACT-1 agent-context
planning capture, pinned concept test package + preparation utility,
foundation observation notes (durability, evidence, federation,
onboarding, workflow), and the #1495 consolidation assessment.
TOOLS.md updated for the host-dev launcher.
2026-09-07 14:07:05 -05:00
jason.woltje 7c580a5625 feat(agents): darkwing host-dev launcher + entry-point consolidation
scripts/agent.sh --host-dev delegates to scripts/agent-host-dev.sh;
agents/darkwing/launch.sh provides the native development TUI
(context, skills, coding tools, /goal). Root SOUL.md is the M14-era
default-collaborator persona captured by the ACT-1 context work.
Launcher regression checks pass (test-darkwing-launch.mjs).
2026-09-07 14:06:54 -05:00
jason.woltje 8ebddd6f93 feat(foundation): offline synthetic scope/permission inspector (FI-FILBERT-8 APPROVED r6)
Rocko-authored, Filbert-reviewed inspector (r6 manifest
a4a44930...) with full review/build/verdict evidence under
docs/plans/reviews. 43/0 selftests, oracle zero-disagreement,
foundation checker PASS. Owner A9 acceptance recorded separately.
2026-09-07 14:06:35 -05:00
jason.woltje 127a54fdff chore: consolidate new foundation and archive v1 (#1495) 2026-09-07 12:32:57 -05:00
Dewey 9a5fbdbda7 fix(goal): quiet waits and unify fleet NG ownership (#56, #57, #58) 2026-09-06 04:07:09 -05:00
jason.woltje 7345f330fc docs: map foundation to integrated rewrite baseline 2026-09-06 02:40:05 -05:00
jason.woltje d4696d09eb feat(extensions): establish canonical goal source (#54, #55) 2026-09-06 02:32:32 -05:00
jason.woltje 44f257cb06 docs: record accepted phase-2 foundation contract 2026-09-06 02:23:15 -05:00
code-infra-01andorch-01 5d27700026 fix(#1257): confirm delivery by draft transition, not prompt detection (adopts #1262) (#1332)
ci/woodpecker/push/publish Pipeline was successful
Co-authored-by: code-infra-01 <[email protected]>
2026-09-04 22:25:13 +00:00
jason.woltje 69d1bb3aa4 docs(plan): resolve harness IDs + lifecycle review gate (#50)
Owner adjudication:
- canonical harness IDs match executables: pi, claude, codex, opencode
- agent.json uses one scalar harness ID; registry/manifest resolution, no
  hard-coded schema enum
- target mosaic harness list/detect/install/rm/status lifecycle
- detection recognizes reviewed executables and records compatibility
  without reading/copying harness homes
- installs are exact-version/verified, Mosaic-managed, never global
- detected external harness is available but not container-ready until
  imported/installed, absent a separately reviewed host adapter

Gate 1 resolved. Remaining P0/review gates stay open; no implementation
authorized. Suites 24/15/90/14/17 + verify green; unslop clean.
2026-09-04 12:26:57 -05:00
jason.woltje 9ea7dea711 docs(review): record independent glm-5.3 auth-registry spec review (#50)
Verdict ACCEPT WITH CHANGES. Persist ten-gate recommendations and three
P0 blockers: per-seat launch provider/model resolution; rotating OAuth
persistence for long-running seats; role auth ceiling ∩ settings profile
plus data-map/reset alignment. Reviewer made no repo edits.

Implementation remains blocked pending owner/conductor adjudication.
Prior gate remains green: suites 24/15/90/14/17 + verify.
2026-09-04 12:14:48 -05:00
jason.woltje d9a94f51ba docs(plan): specify harness declaration + centralized auth/provider registry (#49)
Design only; implementation blocked pending owner review.

- agent.json: one harness identifier (pi first), resolved through a
  versioned adapter/harness manifest; reusable settingsProfile reference
- central data-root registry: providers, accounts (metadata + secret
  credential split), reusable settings profiles, audited runtime selection
- per-seat pi auth.json/models.json mechanically generated and atomically
  activated; no seat/provider registration ceremony
- mixed oauth/api-key accounts supported centrally; one active account per
  provider per pi materialization
- host-side centralized OAuth login/refresh; agents never authenticate
- local/remote Ollama modeled as endpoint providers, not accounts
- target mosaic auth/provider/agent settings CLI; secrets never on argv
- migration, fail-closed acceptance suites, and ten explicit review gates

CURRENT.md points only to spec review. Suites 24/15/90/14/17 + verify
green; unslop clean.
2026-09-04 11:57:40 -05:00
jason.woltje 975084abe2 fix(auth): mosaic-managed auth lives under the data root, never ~/.pi (#48)
Owner direction: the stack must never impact default harness usage.
Correction to M19 as shipped (nothing had been created in ~/.pi — the
move breaks nothing).

- Mosaic-managed accounts: <dataRoot>/auth/<account>.json, perms 0600
  enforced (loose perms flagged in listings, refused by --auth — mirrors
  gitea-api.sh credential hygiene).
- ~/.pi is read-only to the stack, permanently; the only interaction
  remains the existing read-only container mount of the default
  credential. Recorded as a ROADMAP standing decision.
- auth.sh is now config-driven (data root from config.json, fail closed,
  consistent with every other tool); status reports both sources labeled.
- agent.sh --auth resolution moved after load_config (needs the data
  root); missing/symlinked/non-0600 accounts refuse.
- test-auth.sh: 15 no-Docker cases (accounts-create-nothing, loose-perms
  refusal, invalid-config refusal added). Test-authoring correction
  recorded in BUILD-LOG (fixture-state mismatch caught before running).

Suites 24/15/90/14/17 + verify green.
2026-09-03 22:53:33 -05:00
jason.woltje 073bbfdb6a feat(auth): M19 harness auth tooling — auth.sh checkpoint + per-launch account injection (#47)
Investigation (pi 0.84.4 docs + host auth.json metadata, values never
read): provider stacking is native (one auth.json keyed by provider;
resolution --api-key > auth.json > env > models.json; OAuth auto-refresh).
Multi-account per provider is NOT native -> named-file design:
auth.<account>.json + per-launch injection.

- scripts/auth.sh: status (provider names, credential types, perms,
  env-side names informational — never credential material) and accounts
  (named files, active marker). Exit codes per convention: 3 missing for
  a read, 2 unparseable, 4 file/environment (symlinks refuse).
- scripts/agent.sh --auth <account>: resolves auth.<account>.json and
  exports PI_AUTH_FILE (the existing compose read-only mount source — no
  new plumbing); missing/invalid account refuses pre-container.
- scripts/test-auth.sh: 13 no-Docker cases; core assertion is the safety
  property itself — fixture key/token/env VALUES never reach output.
- Docs: TOOLS.md Auth section, AGENTS.md command surface + suites.

Headless task runs keep the default credential (worker auth selection is
a separate policy decision). Real-host smoke: anthropic/openai-codex
oauth + zai api_key reported, perms 600, no named accounts yet.

Suites 24/90/14/17/13 + verify green. Agreed sequence M16-M19 complete;
M20 owner-gated.
2026-09-03 19:58:50 -05:00
jason.woltje d1d7b5598d feat(agent): fail-closed seat resolution under MOSAIC_AGENTS_DIR override (#46)
Owner decision after live verification of M18: an explicit agents-dir
override that cannot resolve the named seat now refuses the launch
(exit 4, names the seat and dir) instead of launching seatless and
unbounded. Unsetting the override keeps the M13 plain governed TUI.
MOSAIC_ROLES_DIR needs no symmetric change - the M18 gate already
refuses unresolvable role contracts.

Task suite 88 -> 90 (refusal + refusal-names-the-seat). TOOLS.md Agent
section documents the refusal.

Suites 24/90/14/17 + verify green.
2026-09-03 19:45:10 -05:00
jason.woltje ca8135d70c feat(roles): M18 seat-role progressive capability restriction (#45)
Role contracts (roles/<role>.json): roleVersion, name bound to filename,
tools ceiling (subset of pi built-ins), network declared (none|api-only|
open; enforced when network policy lands). Strict schema, fail closed -
a non-role document refuses resolution.

mosaic-task.mjs resolve-role: config-free contract validation, emits
MOSAIC_ROLE_TOOLS / MOSAIC_ROLE_NETWORK.

agent.sh: a declared role binds to its contract. Missing/invalid contract
refuses the launch (exit 2, names the role - the under-equipped-seat
failure mode, mirroring M17 skills). Effective tools = ceiling ∩ requested
(CLI --tools or agent.json caps); no request -> ceiling stands; narrowing
and tool-free outcomes loud on stderr. Adapters unchanged; headless M9
chain (mission ∩ task) untouched.

Ships roles/researcher.json (existing seat declares the role; without the
contract the fail-closed gate would refuse its launch).

Task suite 74 -> 88: contract resolution, wrong-kind/name/network/
duplicate/unsupported/missing refusals, ceiling narrowing E2E (mock
adapter), tool-free E2E, missing-contract refusal. Test-authoring
correction recorded in BUILD-LOG (a check that registered on one path
only, caught by count arithmetic).

Suites 24/88/14/17 + verify green.
2026-09-03 17:25:17 -05:00
jason.woltje bf56583a49 docs(skills): owner loop-doctrine + collaborator delivery discipline, remediated (#44)
ms-communications: integrated as-authored - owner preamble restructure +
collaborator delivery-discipline hunks from the #43 calibration (own
session output is not a send path; the tool performs the preamble flip;
receiving rule 3 requires actually running agent-send.sh).

ms-conductor: collaborator redraft integrated (canon-aligned tracking
surfaces, one-action cadence, fail-closed core) with one conductor
remediation - step 3 now distinguishes refusal (fail closed, never
bypass) from runner outage (direct dispatch to a qualified live seat via
ms-communications permitted, recorded loudly as degraded: no sandbox, no
run record; suites still gate integration). Preserves the owner's
outage-dispatch intent inside invariant 6.

docs/TOOLS.md: release.sh ensure row added (M16 subcommand existed in
code but not in the doc - flagged by the collaborator, verified in
release.sh usage).

Authorship: owner (ms-conductor doctrine, preamble restructure) +
ms-test collaborator (delivery hunks, redraft); remediation + integration
by conductor (dragon-lin:darkwing). Suites 24/74/14/17 + verify green;
unslop clean.
2026-09-03 17:17:29 -05:00
jason.woltje c8f433131c docs: calibration phase 22 record; CURRENT.md staleness corrected (M16/M17 late-logged, next M18); session registered (#43) 2026-09-03 16:55:31 -05:00
jason.woltje d1e75f855c docs(tools): document tools/ tree in TOOLS.md + fix stale suite counts (#43)
Collaborator-authored via conductor-loop calibration: task dispatched to the
live ms-test seat (glm-5.3-flash) over agent-send.sh; diff reviewed line by
line and every documented flag/exit code independently verified against tool
source by the conductor; suites green at integration (config 24 / task 74 /
release 14 / conductor 17 + verify).

- new 'Tools (host-side)' section: agent-send.sh, agent-watch.sh, unslop-check.js
- intro reading guide now points at tools/ (worker-flagged addition, accepted)
- Maintenance suite counts corrected: test-task.sh 58 -> 74

Authored-by: ms-test collaborator (glm-5.3-flash)
Integrated-by: conductor (dragon-lin:darkwing)
2026-09-03 16:55:25 -05:00
jason.woltje f710bf1a68 docs: KICKSTART file 2026-09-03 16:34:20 -05:00
jason.woltje 2085d75190 docs: ms-communications skill (owner-authored) + session registry entry + KICKSTART recovery file 2026-09-03 16:34:03 -05:00
jason.woltje 2f5a8d2cec feat(skills): skill lifecycle + ms-* skill set completion (#40, #41, #42)
- scripts/skill.sh: install (bundled or path) / activate / deactivate /
  uninstall (refuses while enabled) / list
- skills-enabled + skills-available dirs under the data root; a skill not
  in skills-enabled is not enabled or available for use
- pi adapter: MOSAIC_SKILLS -> --skill per dir; --no-skills when none
- agent.sh: seat definitions declare skills[]; resolution against
  skills-enabled refuses the launch loudly when missing
- ms-* skills completed (owner-authored canon, hands-off): ms-tools
  adapted to the runtime, ms-file-read/write/agent/conductor bodies
  written in the owner's style; ms-agent-watch + ms-unslop untouched
- tasks/USER.md onboarding fixtures; suite hardening (nested def path,
  user seed, mock-adapter dispatch evidence)

Suites: config 24, task 74, release 14, conductor 17, verify PASS.
RELEASE 0.0.12 packaged; health-gated activation on merge.

Closes #40, closes #41, closes #42
2026-09-03 16:23:57 -05:00
jason.woltje e14ad9ab52 Merge: skill lifecycle, skills completion, M16 self-determination hardening, M20 decision
- skill.sh lifecycle (install/activate/deactivate/uninstall/list)
- 8 ms-* skills completed (owner canon preserved)
- seat skills dispatch + enabled-dir resolution
- M16: ensure at launch, drift warnings, recursion guard
- M20 decision: packages/* monorepo at usurpation

Closes #40, closes #41, closes #42
2026-09-03 16:03:05 -05:00
jason.woltje 9fd16b9739 feat(release): recursion guard for the health gate; run-task drift warning; M20 packages/* decision recorded (#39)
- release.sh health gate runs with MOSAIC_ENSURE_SKIP=1: the gated task run
  cannot re-enter release self-determination
- run-task.sh warns on release drift instead of silently using a stale image
- ROADMAP: M20 decision recorded (packages/* monorepo at usurpation,
  continuity-first); restructure sequenced as M20 phase 1

Closes #39
2026-09-03 15:58:46 -05:00
jason.woltje 9051ad179b docs(roadmap): restructure sequencing (M20 phase 1, not first) + skills-as-discipline doctrine 2026-09-03 14:50:59 -05:00
jason.woltje 2f649ed930 docs: README release ensure row 2026-09-03 14:43:25 -05:00
jason.woltje db330c12c7 feat(release): self-determination - ensure at launch, drift warnings, M20 packages/* decision (#38)
- release.sh ensure: aligned no-op; drift -> package-if-needed + health-gated
  activate (M3 gate-then-flip, automated)
- ensure_release_aligned in common.sh: invoked by hello/verify/agent;
  MOSAIC_ENSURE_SKIP guards recursion; run-task warns on drift without
  auto-aligning (workers/suites never trigger builds or model gates)
- ROADMAP: M20 decision recorded - v2 adopts packages/* monorepo at usurpation
- BUILD-LOG Phase 20 + tool-race process note

Live-verified: post-reset pointer loss auto-restored via health-gated
ensure; drift warning fires on desired-version bump; idempotent no-op on
aligned state.

Closes #38
2026-09-03 14:42:09 -05:00
jason.woltje 0a17d29bce docs(roadmap): flush 2026-09-03 14:28:58 -05:00
jason.woltje 3458f6a7ad docs(roadmap): M17 skill lifecycle (skills-enabled/available, role-scoped subsets, --skill negates --no-skills); M20 stack succession path + monorepo question 2026-09-03 14:28:45 -05:00
jason.woltje b033952cd5 docs(harvest): pattern ledger from stack/next + fleet runtime (12 patterns, skips, owner-corrected M17-M19 designs) 2026-09-03 13:55:30 -05:00
jason.woltje c102980ad4 docs(plan): CURRENT.md - queue aligned to ROADMAP (M16 next, CI deferred) 2026-09-03 12:59:28 -05:00
jason.woltje 58b96cb715 docs(plan): ROADMAP.md - M16 release self-determination, M17 ms-tools skill, M18 seat-role restriction, M19 auth tooling; CI deferred per owner 2026-09-03 12:57:26 -05:00
jason.woltje dd3ff944a1 chore(release): 0.0.11 2026-09-03 12:30:52 -05:00
jason.woltje 8eb81ebec1 feat(onboard): user onboarding - no default USER.md, guided creation (#37)
- bootstrap no longer creates user/USER.md (owner direction)
- scripts/onboard.sh: name REQUIRED (interactive loop or --name),
  optional fields prompted (profession, marital, age, gender, education,
  location, timezone, skillset, interests, hobbies, pets); flag-driven
  non-interactive mode for automation
- templates/USER.md: canon skeleton, placeholder rendering, unfilled
  optional = (not provided)
- agent.sh: auto-runs onboarding when profile missing (TTY gate);
  headless run-task warns and continues without user context
- user profile dispatched to all launches (M14 layer)

Closes #37 (onboarding requirements from owner layout review)
2026-09-03 12:30:42 -05:00
jason.woltje 530597cc84 docs(plan): CURRENT.md flush 2026-09-03 11:59:49 -05:00
jason.woltje 9a0d44f96a docs(plan): CURRENT.md - deduplicated completed log (marked correction), M15 review queued 2026-09-03 11:59:37 -05:00
jason.woltje 121b331c6c docs(log): back-fill phases 16-19 (M10, M12, M14, M15) - recorded retroactively with ground-truth sources 2026-09-03 11:59:14 -05:00
jason.woltje 34e06e7de7 Merge M15: agent seats - per-agent SOUL and role contracts
Closes #36
2026-09-03 11:56:38 -05:00
jason.woltje 9bd4f1c405 feat(agents): agent seats - per-agent SOUL, role, definitions dir (#36)
- agents/<name>/ holds agent.json (strictly validated: version, name,
  role?, capabilities?, workspace?, session?) + SOUL.md (persona prose)
- agent.sh: definition loading (quote-safe node defaults file), runtime
  SOUL copy to dataRoot/agents/<name>/, MOSAIC_AGENT_SOUL_FILE ->
  loader fills the SOUL slot from the seat's persona (contract SOUL =
  default persona; governance never overridden)
- seat.json written once at instantiation (seatVersion, name, role, at)
- identity section gains agent role; compose passthrough for role+SOUL
- live user context (M14) + seat SOUL compose the full persona:
  governance -> persona -> identity -> user -> mission
- RELEASE -> 0.0.10; packaged and health-gated activated
- example seat committed: agents/researcher

Closes #36
2026-09-03 11:56:38 -05:00
jason.woltje a7b612435b docs: BUILD-LOG Phase 15, CURRENT.md - M13 shipped 2026-09-03 11:25:41 -05:00
jason.woltje 87f10772ce Merge M13: interactive TUI agent + TOOLS.md
Closes #35
2026-09-03 11:24:56 -05:00
jason.woltje 7db4c5c2ed feat(agent): interactive TUI launcher + identity + TOOLS.md (#35)
- scripts/agent.sh <name>: launches interactive pi TUI in the container
  with contracts + optional mission + agent identity + named session +
  optional workspace/tools; the Mosaic alternative to vanilla pi
- pi adapter: MOSAIC_INTERACTIVE branch (clean TUI, no -p, no initial
  prompt); headless exec rebuilt via positional args (no word-splitting
  on the request); MOSAIC_AGENT_NAME optional in headless
- loader: AGENT IDENTITY section when the launcher names the agent
- compose: fixed command removed (request defaults live in run-agent.sh);
  MOSAIC_INTERACTIVE/MOSAIC_AGENT_NAME passthrough
- docs/TOOLS.md: full on-demand tool reference; AGENTS.md routes to it
- RELEASE -> 0.0.8 (container change); build verified

Closes #35
2026-09-03 11:24:56 -05:00
jason.woltje 0273a84549 docs: AGENTS.md - session recovery shim, invariants canon, session registry
- AGENTS.md at root: pi loads it automatically at every session start
  (conductor-level sessions; workers deliberately exclude it via
  --no-context-files). Deliberately short: invariants, session protocol,
  role model, command surface, data map, pointers - depth stays in docs/.
- docs/SESSIONS.md: append-only session registry, mandatory per session.
- Recovery rule encoded: compaction/restart loses nothing - AGENTS.md +
  CURRENT.md + git log + suites reconstruct state; never guess.
2026-09-03 11:02:19 -05:00
jason.woltje 3b674b7a66 Merge: roles/ directory convention - root is bootstrap-only 2026-09-03 10:56:07 -05:00
jason.woltje 527bc581ca refactor(layout): role contracts move to roles/ - root is bootstrap-only
Owner direction: the repository root holds first-class, bootstrap-required
configuration only. conductor-policy.json is a ROLE contract (the
conductor's authority), one of scores of future role contracts
(agent-policy, coder-policy, ...) - such files get a dedicated home.

- roles/conductor-policy.json (git mv)
- conductor-apply.sh + test-conductor.sh read the new path
- CONDUCTOR.md records the roles/ convention

Closes UX follow-up from owner layout review; no issue (convention change).
2026-09-03 10:56:07 -05:00
jason.woltje 1249714a9a docs(plan): CURRENT.md - M12 shipped 2026-09-03 07:04:37 -05:00
orch-01 d6302f8e6f docs: make Portainer optional deployment path (#1492)
ci/woodpecker/push/publish Pipeline was successful
2026-09-02 23:23:07 +00:00
marcieandorch-01 9aa4983cf2 fix: use canonical dogfood seat identity (#1490)
ci/woodpecker/push/publish Pipeline was successful
Co-authored-by: marcie <[email protected]>
2026-08-30 23:43:22 +00:00
marcieandorch-01 736b0affc1 compose: add wrapper-first dogfood workspace (#1488)
ci/woodpecker/push/publish Pipeline was successful
Co-authored-by: marcie <[email protected]>
2026-08-30 22:29:30 +00:00
orch-01 e18d13d36f fleet: split-home-safe mosaic launcher (T110, P5-RM-009 stack side) (#1480)
ci/woodpecker/push/publish Pipeline was successful
2026-08-30 10:05:40 +00:00
marcieandorch-01 60bc5d2022 compose: pin MOSAIC_STORAGE_TIER=standalone (A5d formal-run fix) (#1486)
ci/woodpecker/push/publish Pipeline was successful
Co-authored-by: marcie <[email protected]>
2026-08-30 07:49:35 +00:00
marcie ea91cfc421 compose: stack profile — one-command standalone deployment (A5) (#1485)
ci/woodpecker/push/publish Pipeline was successful
2026-08-30 06:03:39 +00:00
marcie acf640d00f docs: containerization plan + PRD D15 (tiered deployment, standalone v1 bar) (#1484)
ci/woodpecker/push/publish Pipeline was successful
2026-08-30 05:21:42 +00:00
fredandmarcie 431ead3a18 feat(gateway,cli): agent enrollment command family (M4-4b) (#1483)
ci/woodpecker/push/publish Pipeline was successful
Co-authored-by: fred <[email protected]>
2026-08-30 04:30:05 +00:00
fred 143ba0f57a db: agent enrollment schema (M4-4a, migration 0021) (#1482)
ci/woodpecker/push/publish Pipeline was canceled
2026-08-30 01:47:06 +00:00
fred ee815a72b1 docs: agent enrollment command family v1 design (M4-4-0) (#1481)
ci/woodpecker/push/publish Pipeline was canceled
2026-08-30 01:21:00 +00:00
marcieandorch-01 94d626dff9 mosaic comms: socket resolution is tool-owned (B2) (#1476)
ci/woodpecker/push/publish Pipeline was successful
Co-authored-by: marcie <[email protected]>
2026-08-29 23:35:37 +00:00
marcieandorch-01 ee6c842918 R3: --body-file <path>/- across body/comment carriers (#1474)
ci/woodpecker/push/publish Pipeline was canceled
Co-authored-by: marcie <[email protected]>
2026-08-29 22:49:20 +00:00
marcieandorch-01 ba3b854d50 D1/D3: --number canonical on issue wrappers, --labels alias on list wrappers (#1475)
ci/woodpecker/push/publish Pipeline was canceled
Co-authored-by: marcie <[email protected]>
2026-08-29 22:29:16 +00:00
fred c7a7fd07cc brain/gateway: prohibit mission_tasks.status as a write source (M4-3a phase 1) (#1479)
ci/woodpecker/push/publish Pipeline was canceled
2026-08-29 21:59:13 +00:00
fred 5399c6b7e7 docs: P0 field-map currency verification at next@abb0c936 (M4-3a-0) (#1478)
ci/woodpecker/push/publish Pipeline was canceled
2026-08-29 21:17:05 +00:00
marcieandorch-01 e09b8783b4 P1b: read-only viewers join the R1/R4 usage contract (#1472)
ci/woodpecker/push/publish Pipeline was canceled
Co-authored-by: marcie <[email protected]>
2026-08-29 21:03:07 +00:00
marcieandorch-01 abb0c93601 framework tools/tmux: agent-send socket default resolution + ambiguity guard (B1) (#1466)
ci/woodpecker/push/publish Pipeline failed
Co-authored-by: marcie <[email protected]>
2026-08-29 20:25:50 +00:00
marcieandorch-01 e67cced273 mosaic fleet logins: per-seat credential pass-through (P4 gap closure) (#1473)
ci/woodpecker/push/publish Pipeline was canceled
Co-authored-by: marcie <[email protected]>
2026-08-29 20:05:23 +00:00
fred 635cb1f666 docs: contract 2 Amendment 1 — company-CRUD capability (S2 follow-up) (#1477)
ci/woodpecker/push/publish Pipeline was canceled
2026-08-29 19:34:48 +00:00
marcieandorch-01 09d24b9275 pr-merge --base-line: gated intra-line exception (B5) (#1471)
ci/woodpecker/push/publish Pipeline was successful
Co-authored-by: marcie <[email protected]>
2026-08-29 18:14:40 +00:00
marcieandorch-01 ed4c543872 mosaic coord: board subcommand + roll alias (P3 gap closure) (#1470)
ci/woodpecker/push/publish Pipeline was canceled
Co-authored-by: marcie <[email protected]>
2026-08-29 17:52:30 +00:00
fred 215faeda0a feat(hierarchy): M4-1b-ii hierarchy command family, grant evaluation, visibility (#1465)
ci/woodpecker/push/publish Pipeline was canceled
2026-08-29 16:54:39 +00:00
orch-01 5125fe21b0 p0 line landing: coord board/roll + wrapper usage contract + dispatch layer (successor to #1467) (#1468)
ci/woodpecker/push/publish Pipeline was canceled
Co-authored-by: orch-01 <[email protected]>
2026-08-29 16:24:08 +00:00
marcieandorch-01 41e8046371 framework tools/git: issue-comment R1/R4 usage-error contract (sync from brain) (#1462)
ci/woodpecker/push/publish Pipeline failed
Co-authored-by: marcie <[email protected]>
2026-08-29 01:58:42 +00:00
fred 6e16675ea2 docs: deployment mode and conversion contract (S2 contract 6) (#1439)
ci/woodpecker/push/publish Pipeline was successful
2026-08-28 22:57:11 +00:00
fred 19ebc422aa docs: tool-gateway mapping contract (S2 contract 5) (#1438)
ci/woodpecker/push/publish Pipeline was successful
2026-08-28 22:04:03 +00:00
fred bd749831b1 docs: company visibility classes (Ruling 4b amendment, contracts 1+3) (#1461)
ci/woodpecker/push/publish Pipeline was successful
2026-08-28 20:17:35 +00:00
fred f8e1b43b5b docs: RBAC grant model contract (S2 contract 2) (#1436)
ci/woodpecker/push/publish Pipeline is running
2026-08-28 19:09:17 +00:00
fred 2148c20d26 feat(hierarchy): audit event + outbox machinery (M4-1b-i, contract 1 §5.2) (#1460)
ci/woodpecker/push/publish Pipeline was successful
2026-08-28 02:22:53 +00:00
fred 5964dab891 feat(db): hierarchy record class schema + witnesses (contract 1, M4-1a) (#1459)
ci/woodpecker/push/publish Pipeline was successful
2026-08-28 00:42:35 +00:00
orch-01 bdb903cf69 docs: T78 official CLI capability migration contract (#1458)
ci/woodpecker/push/publish Pipeline was successful
2026-08-27 19:53:51 +00:00
fred bec2eb118b docs: API contract artifacts contract (S2 contract 9) (#1443)
ci/woodpecker/push/publish Pipeline was successful
2026-08-27 19:18:39 +00:00
fred 07624140e4 docs: hierarchy schema contract (S2 contract 1, D2) (#1435)
ci/woodpecker/push/publish Pipeline was canceled
2026-08-27 16:39:15 +00:00
fred 1c79af25d4 fix(mosaic): retry the Invariant R pi version probe under CI load (#1441)
ci/woodpecker/push/publish Pipeline was canceled
2026-08-27 16:38:53 +00:00
fred e605c83b27 ci(web): Phase P6 — vite build + headless E2E gate on every trunk merge (#1445) (#1454)
ci/woodpecker/push/publish Pipeline was successful
2026-08-27 15:26:10 +00:00
fred b5ee692843 P5: SPA cutover — retire Next.js, gateway serves the Vite bundle (#1444) (#1453)
ci/woodpecker/push/publish Pipeline was successful
2026-08-27 13:06:49 +00:00
fred bf8bc2128d fix(docker): copy scripts/ into appservice builder before pnpm install (#1452)
ci/woodpecker/push/publish Pipeline was successful
2026-08-27 11:28:47 +00:00
fred 01904b8f69 docs: custody pointer and consent schema contract (S2 contract 7) (#1440)
ci/woodpecker/push/publish Pipeline failed
2026-08-27 10:39:32 +00:00
fred 676900bd46 docs: onboarding wizard contract (S2 contract 3) (#1437)
ci/woodpecker/push/publish Pipeline was canceled
2026-08-27 10:39:23 +00:00
fred a3b0770205 docs: roll-up projection contract (S2 contract 8) (#1442)
ci/woodpecker/push/publish Pipeline was canceled
2026-08-27 02:10:12 +00:00
fred 2a30c68b84 docs: identity account-lifecycle contract (S2 contract 4) (#1433)
ci/woodpecker/push/publish Pipeline is running
2026-08-27 00:13:49 +00:00
fred f8f8f97be7 feat(web): port settings and admin surfaces into the SPA (Phase P4-2) (#1434)
ci/woodpecker/push/publish Pipeline was canceled
2026-08-27 00:03:38 +00:00
fred 49b7943420 fix(gateway): scope /api/teams endpoints to team membership (#1428) (#1429)
ci/woodpecker/push/publish Pipeline is pending
2026-08-26 22:45:54 +00:00
fred 19e16bd44f ci: publish web+appservice sha images on next (#1407) (#1427)
ci/woodpecker/push/publish Pipeline was canceled
2026-08-26 22:42:03 +00:00
jason.woltje 3bd490c080 Merge pull request 'docs: north-star PRD rewrite (D1-D14), ROADMAP, kanban SOT Amendment A1' (#1425) from docs/prd-north-star-rewrite into next
ci/woodpecker/push/publish Pipeline was successful
Reviewed-on: #1425
2026-08-26 16:57:16 +00:00
fred 4b448109dd docs/prd: address independent review findings 1-10 (fidelity, A1 record class + carve-out, roadmap completeness)
ci/woodpecker/pr/ci Pipeline was successful
2026-08-25 23:20:40 -05:00
fred bc1149c15e docs: north-star PRD rewrite (D1-D14), ROADMAP.md, kanban SOT Amendment A1
ci/woodpecker/pr/ci Pipeline was successful
- docs/PRD.md: Part I product north star authored from ratified decisions
  D1-D14; Part II preserves all active workstream contracts verbatim
  (KBN-101, FCM #758, FCOM #766, TESS, #756, MOS-PORT, #1150, #1174, #1194,
  RI #1275, M1). Referenced anchors unchanged.
- docs/archive/PRD-v0.1.md: v0.1.0 beta PRD body archived verbatim with
  supersession header.
- docs/ROADMAP.md: all phases P0-P5 present from day one per D11
  (P2-P5 as explicit placeholders).
- docs/requirements/native-kanban-sot.md: Amendment A1 (D13) - hierarchy
  parentage + RBAC chain above workspaces; sections 1-7 untouched.
2026-08-25 22:23:07 -05:00
orch-01 089953a7cf ci: enable turbo remote cache on trusted publish events (#1424)
ci/woodpecker/push/publish Pipeline was successful
Co-authored-by: orch-01 <[email protected]>
2026-08-25 18:32:55 +00:00
ops-deploy-01 7b25be22e9 fix(#1394): recover-token headless — dual path (--email flag + piped stdin) with documented precedence (#1423)
ci/woodpecker/push/publish Pipeline was successful
Co-authored-by: ops-deploy-01 <[email protected]>
2026-08-25 16:14:56 +00:00
ops-deploy-01 4e3d179e61 fix(#1390): gateway uninstall headless — --yes/--remove-data; non-TTY without consent fails loud (#1422)
ci/woodpecker/push/publish Pipeline was canceled
Co-authored-by: ops-deploy-01 <[email protected]>
2026-08-25 16:00:17 +00:00
ops-deploy-01andorch-01 ae58482b72 fix(#1392): review-285 N1+N2 follow-up — env has no config authority in schema-check; verification throws fatal at install (#1421)
ci/woodpecker/push/publish Pipeline was canceled
Co-authored-by: ops-deploy-01 <[email protected]>
2026-08-25 15:08:04 +00:00
code-infra-01 b2d40dada0 fix(#1391): boot-time ValidationPipe metatype self-check — fail loud at startup (#1419)
ci/woodpecker/push/publish Pipeline was successful
Co-authored-by: code-infra-01 <[email protected]>
2026-08-25 14:01:24 +00:00
code-be-02andorch-01 d30a4cce00 feat(git-tools): consume .mosaic/repo.json declarations in compat mode (T51 WP5b) (#1416)
ci/woodpecker/push/publish Pipeline failed
Co-authored-by: code-be-02 <[email protected]>
2026-08-25 12:55:40 +00:00
veronicaandorch-01 4cd280e48d feat(tools/git): grant-reviewer.sh org-team reviewer grant with fail-closed read-back (#1415) (#1417)
ci/woodpecker/push/publish Pipeline failed
Co-authored-by: veronica <[email protected]>
2026-08-25 02:30:33 +00:00
code-infra-01andorch-01 8738a03893 fix(#1395): accounts.issuer column + credential-only backfill — password auth on fresh installs (#1401)
ci/woodpecker/push/publish Pipeline failed
Co-authored-by: code-infra-01 <[email protected]>
2026-08-25 01:19:29 +00:00
code-be-01andorch-01 04a01be992 ci(publish): serialize workspace-consuming image builds after publish-next-npm (#1411) (#1412)
ci/woodpecker/push/publish Pipeline was canceled
Co-authored-by: code-be-01 <[email protected]>
2026-08-25 01:18:02 +00:00
veronicaandorch-01 812e2df1da fix(#1408): mosaic-agent@ condition arms on either home shape (#1410)
ci/woodpecker/push/publish Pipeline was canceled
Co-authored-by: veronica <[email protected]>
2026-08-25 01:17:15 +00:00
veronicaandorch-01 8c292fb32f fix(#1408): legacy-socket launch guard + seat launch.sh preference (#1409)
ci/woodpecker/push/publish Pipeline was canceled
Co-authored-by: veronica <[email protected]>
2026-08-25 00:49:27 +00:00
code-be-01andorch-01 f45928c311 fix(ci): restore workspace manifests after publish pin transform (#1404) (#1405)
ci/woodpecker/push/publish Pipeline failed
Co-authored-by: code-be-01 <[email protected]>
2026-08-25 00:08:40 +00:00
ops-deploy-01andorch-01 4d24ae8618 fix(#1392): hash-ledger migrations + install-time schema verification (closes #1392, closes #1402) (#1403)
ci/woodpecker/push/publish Pipeline failed
Co-authored-by: ops-deploy-01 <[email protected]>
2026-08-24 23:11:50 +00:00
code-be-01andorch-01 d790572e2e ci(publish): pin next-channel @mosaicstack deps to exact same-pipeline builds (#1389) (#1400)
ci/woodpecker/push/publish Pipeline was canceled
Co-authored-by: code-be-01 <[email protected]>
2026-08-24 23:05:37 +00:00
code-be-01andorch-01 d7b1dd9601 test(git-tools): wrapper-guard harness distinguishes tool failure from drift (#1380-FF) (#1388)
ci/woodpecker/push/publish Pipeline was successful
Co-authored-by: code-be-01 <[email protected]>
2026-08-24 21:43:09 +00:00
code-be-01andorch-01 0db2d19a22 feat(framework): mosaic doctor structure-anchor provisioning check (T51 WP0b) (#1379)
ci/woodpecker/push/publish Pipeline was successful
Co-authored-by: code-be-01 <[email protected]>
2026-08-24 20:15:08 +00:00
code-be-01andorch-01 8eb7e6354e fix(fleet): resolve-then-validate symlink guard + framework helper resolution (#1380) (#1383)
ci/woodpecker/push/publish Pipeline failed
Co-authored-by: code-be-01 <[email protected]>
2026-08-24 19:39:13 +00:00
code-be-01andorch-01 9014a510a9 ci(mosaic): repo-structure declaration CI gate (T51 WP5c) (#1378)
ci/woodpecker/push/publish Pipeline was successful
Co-authored-by: code-be-01 <[email protected]>
2026-08-24 04:43:26 +00:00
code-be-01andorch-01 974e4740ab docs(mosaic): declare repo structure v2 (T51 WP2a) (#1377)
ci/woodpecker/push/publish Pipeline was successful
Co-authored-by: code-be-01 <[email protected]>
2026-08-24 03:49:33 +00:00
orch-01 9cd6d39b71 fix(git-tools): pr-create API fallback resolves base from forge default branch (E4) (#1376)
ci/woodpecker/push/publish Pipeline was successful
2026-08-24 02:49:38 +00:00
code-be-01andorch-01 143f925fd8 fix(git-tools): admin-gated --no-ci-expected merge assertion for CI-less repositories (#1373)
ci/woodpecker/push/publish Pipeline was successful
Co-authored-by: code-be-01 <[email protected]>
2026-08-23 18:54:49 +00:00
fredandgate-merge-01 24294d3b77 fix(git-tools): issue-view shows comment bodies and names the real tea failure (#1357) (#1365)
ci/woodpecker/push/publish Pipeline was successful
Co-authored-by: fred <[email protected]>
2026-08-22 00:23:22 +00:00
veronicaandgate-merge-01 24caeab057 fix(tmux): locate the REPL input box by shape, not by a Claude-only glyph (#1363)
ci/woodpecker/push/publish Pipeline was successful
Co-authored-by: veronica <[email protected]>
2026-08-21 23:45:08 +00:00
fredandgate-merge-01 888a6ad29b fix(#1356): tea login resolution fails closed on a declared git identity (#1361)
ci/woodpecker/push/publish Pipeline was canceled
Co-authored-by: fred <[email protected]>
2026-08-21 23:04:31 +00:00
fred 24462f460e docs(git-wrappers): correct the stale --login fallback and document the test suite's identity split (#1354)
ci/woodpecker/push/publish Pipeline was successful
2026-08-21 14:42:36 +00:00
veronicaandfred a480ee83dc docs(W4): document contract — stamp kind and status on 104 live docs (#1350)
ci/woodpecker/push/publish Pipeline was canceled
Co-authored-by: veronica <[email protected]>
2026-08-21 14:07:36 +00:00
fred fd43ed5420 fix(git-wrappers): no --login must use the caller's own credential, not a guessed shared login (#1352)
ci/woodpecker/push/publish Pipeline was successful
2026-08-21 04:10:42 +00:00
fargoandfred 1d84bc3f3d fix(fleet): lease-broker activation, symlink-safe unit placement, named launch refusal — Wall 6 (#1292) (#1297)
ci/woodpecker/push/publish Pipeline was successful
Co-authored-by: fargo <[email protected]>
2026-08-21 00:40:29 +00:00
fred 6306914965 fix(lease-broker): no lease held is a no-op success, not a denied transition (#1339)
ci/woodpecker/push/publish Pipeline was successful
2026-08-20 23:40:09 +00:00
fred af43a7a63e docs(fleet): tier the north star and declare the tier-0 operator surface (#1337)
ci/woodpecker/push/publish Pipeline was canceled
2026-08-20 23:05:34 +00:00
fred ca97b885b0 fix(#808): never borrow a session identity for non-tmux senders (#1335)
ci/woodpecker/push/publish Pipeline was successful
2026-08-20 21:03:50 +00:00
code-infra-01 6db0bead44 fix(#1327): sentinel-managed PATH block, default-home-only profile writes (#1330)
ci/woodpecker/push/publish Pipeline failed
Co-authored-by: code-infra-01 <[email protected]>
2026-08-20 20:20:33 +00:00
GhostfredGhost <>
c671290d77 docs: define main/next branch model, sequencing, responsibilities, and merge process (#1214) (#1215)
ci/woodpecker/push/publish Pipeline was canceled
Co-authored-by: Ghost <>
2026-08-20 20:19:39 +00:00
code-infra-01andfred 6a9b2cf6c1 fix(git-tools): pr-merge queue guard reads CI status from the BASE repo for fork PRs (B1) (#1334)
ci/woodpecker/push/publish Pipeline was canceled
Co-authored-by: code-infra-01 <[email protected]>
2026-08-20 20:18:59 +00:00
Ghostgate-merge-01Ghost <>
6bd93a621d scratchpads: fleet identity/comms/mosaic-tree continuation record (2026-08-17) (#1296)
ci/woodpecker/push/publish Pipeline was successful
Co-authored-by: Ghost <>
2026-08-20 19:11:59 +00:00
GhostfredGhost <>
e9485c3d96 docs(l0): parameterize hard gates on the project's integration trunk (#1216, Option A) (#1217)
ci/woodpecker/push/publish Pipeline was successful
Co-authored-by: Ghost <>
2026-08-20 18:38:18 +00:00
Ghostgate-merge-01Ghost <>
d2f0846dcc fleet: put the bootstrapped Node on PANE_PATH (#1256) (#1258)
ci/woodpecker/push/publish Pipeline was canceled
Co-authored-by: Ghost <>
2026-08-20 18:31:30 +00:00
fredandgate-merge-01 4f22a58041 guides: two measurement rules about pinned tool versions (#1316)
ci/woodpecker/push/publish Pipeline was successful
Co-authored-by: fred <[email protected]>
2026-08-20 16:40:58 +00:00
Ghostgate-merge-01Ghost <>
9b6869fab7 fix(#1179): require security authority wiring (#1189)
ci/woodpecker/push/publish Pipeline was canceled
Co-authored-by: Ghost <>
2026-08-20 16:19:45 +00:00
ops-ci-01 20ad89c86b docs(ci): state the measured push-CI model in ci.yml's when-comment (#1326)
ci/woodpecker/push/publish Pipeline failed
Co-authored-by: ops-ci-01 <[email protected]>
2026-08-20 15:48:46 +00:00
ops-01 a55d1a1812 Merge pull request 'merge: absorb main into next — 23-commit divergence (08-05..13 base=main window)' (#1324) from merge/main-into-next into next
ci/woodpecker/push/publish Pipeline was successful
2026-08-20 01:07:05 +00:00
ops-01 9abd7e386f chore: serialize CI run — same tree as 9af456c, fresh pipeline head
ci/woodpecker/pr/ci Pipeline was successful
Per ops-ci-01 (PR #1324 comments 23413/23422) and fred's one-at-a-time
authorization: one serialized run of #1324's tree on the pinned image
(ci-base:lock-9cb7ffcd8828, carried since the cb9a0d1 absorb). This commit
changes no files — the tree is identical to 9af456c; it exists only to mint a
fresh pipeline head instead of restarting 2545.
2026-08-19 19:45:20 -05:00
ops-01 9af456c240 merge: absorb next (pin cb9a0d1 + #1325 + #1129) for the controlled pinned-image rerun
ci/woodpecker/pr/ci Pipeline failed
Per ops-ci-01's procedure (comments 23386/23394, brain D27): pipeline config
travels with the commit under test, so the controlled rerun requires the pinned
anchor in the PR head itself. This merge absorbs everything next took since the
original merge parent (1bdeed62): the ci-base pin (cb9a0d1, lock-9cb7ffcd8828),
the legacy-credential removal (#1325), and the ci-queue-wait statuses:null fix
(#1129 — the branch from the divergence analysis, now landed).

One conflict, same file as round 1: test:framework-shell union — our 54-entry
chain plus next's new test-ci-queue-wait-no-status.sh entry at its position
(55 entries, every target existence-verified). Enumeration guard green:
population 61, enumerated 46, excluded (signed) 16.
2026-08-19 18:43:19 -05:00
ops-ci-01 cb9a0d1642 ci: pin ci-base to immutable lock-9cb7ffcd8828 (Closes #1328) (#1329)
ci/woodpecker/push/publish Pipeline was successful
Co-authored-by: ops-ci-01 <[email protected]>
2026-08-19 23:42:05 +00:00
fargo 420507da77 fix(#1323): remove legacy credential read and force-merge recipe from mosaic-gitea (#1325)
ci/woodpecker/push/publish Pipeline was successful
2026-08-19 22:51:35 +00:00
ops-01 2508f0aa99 fix(merge): round-2 CI failures — pipefail sites, verify:release mirror, format
ci/woodpecker/pr/ci Pipeline failed
Pipeline 2534 (018d96a), two test-step failures plus the format failure
root-caused by rev-code-01 (id 202):

1. pipefail-early-exit.test.mjs: main's window wrote the test but never
   wired scripts/*.test.mjs into its own CI, so its tools/install.sh pipes
   were never executed against it; next's test wiring runs them and flags
   two load-bearing pipes. Both rewritten pipefail-safe via process
   substitution (newest_matching_file ls|head, check_fleet_transport
   sed|head|tr|awk). Test now 7/7 locally.

2. verify-release.test.mjs: merge kept main's 9-command ci.yml sanitization
   but next's 4-command canonical stage. Canonical updated to mirror ci.yml
   exactly (9=9, order verified). upgrade-guard checked equal (4=4).

3. format: docs/reports/quality/1099-pipefail-sweep.md (from main f158be8)
   prettier-formatted under pinned 3.8.1.

Enumeration guard re-verified: population 60, enumerated 45, excluded 16.
2026-08-19 17:27:30 -05:00
Ghostops-02Ghost <>
d339e8fd21 fix(git-tools): ci-queue-wait — Gitea statuses:null no longer malformed; CI-less repos pushable again (#1129)
ci/woodpecker/push/publish Pipeline was successful
Co-authored-by: Ghost <>
2026-08-19 22:08:34 +00:00
ops-01 018d96a412 fix(merge): drop fleet test-start-agent-session.sh from framework-shell chain — review B1
ci/woodpecker/pr/ci Pipeline failed
Review stack#1324 id 201 (rev-code-01): the union resolution chained main's #1073
fleet test while keeping next's signed exclusion of it (#1271 burn-down: the test
asserts missing-binary behavior but CI provides pi on PATH — fails by design).
check-test-enumeration CONTRADICTORY EXCLUSION, CI pipeline 2532 terminal failure.

Fix per verified review recommendation: remove the chain entry (55 -> 54 parts),
keeping next's exclusion and #1271 state. Guard now passes:
population 60, enumerated 45, excluded (signed) 16.
2026-08-19 16:44:31 -05:00
ops-01 b01950e92f merge: absorb main into next — 23-commit divergence (08-05..13 base=main window)
ci/woodpecker/pr/ci Pipeline failed
17 content commits + 3 merge bubbles were genuinely missing from next (~8,000 lines:
goal controller #1152, framework enforcement #1174/#1195, pr-edit wrapper #1173/#1200,
pipefail series #1100/#1105/#1106/#1107, git-tools fixes #1073/#1085/#1086/#1089,
#991, #1007, enrollment tolerance #1094). 3 commits were already in next by content
(#1060 identical, #1066/#1062 evolved twins — conflicts resolved to next's side).

Per-commit classification and evidence: mosaic-brain fleet/lanes/stack-remediation/main-next-divergence.md.
Conflict resolutions (6 files) itemized in the PR body.
2026-08-19 16:27:17 -05:00
fargo 1bdeed62eb fix(#1320): placeholder-ize private-network topology, drop raw-curl force-merge recipe (#1322)
ci/woodpecker/push/publish Pipeline was successful
2026-08-19 21:15:54 +00:00
fargo 840c2b0d96 Merge pull request 'skills: fold agent-skills into the monorepo, single install path, promote ms-unslop (plan phase D)' (#1319) from fold-agent-skills into next
ci/woodpecker/push/publish Pipeline was successful
2026-08-19 20:08:09 +00:00
fargo 95d5cb32d4 format: cover folded skills' js/ts scripts with repo prettier
ci/woodpecker/pr/ci Pipeline was successful
The repo format:check glob covers ts/js alongside md; four non-markdown
scripts inside the folded tree were flagged after the md pass. Same pinned
prettier 3.8.1, same markup-only class (verified: node --check still passes
on the js files).
2026-08-19 14:41:18 -05:00
fargo d5f3fae896 skills: promote ms-unslop from skills-local into the package
Phase D3 of plan 2026-08-19 (decision S21): skills-local is the local test
bed; promote individually as each proves out. ms-unslop is the only one of
the seven local skills with working enforcement evidence — a checker
(tools/unslop-hook/unslop-check.js), a machine-source list (lists.json), a
19-test suite, a measured corpus, and a regression fixture.

The checker itself stays fleet-local for now (it binds to a specific
harness extension surface); this promotes the skill document only.

Gates verified on the moved file: sanitization denylist clean, prettier
3.8.1 clean (6730 chars was fred's measure at assignment; 7249 as shipped
today — both pass).
2026-08-19 14:39:46 -05:00
fargo 1556982dbc skills: single install path — canonical skills ship with the framework
Phase D2 of plan 2026-08-19: single package, single install, single command.

The framework installer already treats skills/** as a shipped, manifest-owned
framework subtree, so the folded skills now install into
$MOSAIC_HOME/skills with the rest of the framework — no second repository,
no separate sync step:

- mosaic-sync-skills (bash + powershell): the fetch machinery is gone (clone,
  pull, dirty-state migration, rsync from sources/agent-skills). The script
  now only links installed skills into runtime homes. --link-only is a compat
  no-op; --no-link exits having nothing to do.
- catalog.ts: the sources/agent-skills fallback is dead and removed.
- install.sh, launch.ts, defaults/README.md, README.md, skills/README.md:
  references to the second repo rewritten to describe the shipped path.

Verified: clean install into a fresh MOSAIC_HOME produces 102 skills with no
sources/ directory; the linker then links the selected skills into the four
runtime homes with no git involvement.
2026-08-19 14:39:28 -05:00
fargo 1a822493ba format: apply repo prettier (3.8.1) to the folded skills tree
963 markdown files reformatted with the repository's pinned prettier so
pnpm format:check covers the folded tree like every other repo file.

The formatter's embedded-language pass also normalized code fences
(TS semicolons, closed HTML tags in examples, lowercased CSS hex colors,
one renumbered list that skipped an index). Alphanumeric token deltas vs
the fold commit were audited file-by-file; all are formatter-equivalent
markup normalizations plus the four sanitized skills.
2026-08-19 14:37:17 -05:00
fargo d2eeb64433 skills: sanitize operator-identity tokens from folded ops skills
Four folded skills carried operator identity tokens that the sanitization
gate (verify-sanitized.sh) forbids in the public framework package:

- kickstart: template path pointed at a private brain checkout; now uses the
  framework-shipped $MOSAIC_HOME/templates/docs/TASKS.md.template
- mosaic-deploy: dropped one estate-specific stack-name row from the example
  table
- mosaic-portainer, mosaic-woodpecker: credentials now name the framework
  credentials store (load_credentials <service>) instead of a private
  checkout path

Estate-specific values can live in a skills-local override, which the linker
applies with precedence over canonical skills.
2026-08-19 14:34:00 -05:00
fargo 5e58597dbe fold: absorb mosaicstack/agent-skills into the framework skills tree
Fold the agent-skills repository into the monorepo as the shipped canonical
skills package (plan 2026-08-19 phase D1, decision S19: single package, single
install, single command).

History is preserved by rewriting each commit's paths from skills/ to
packages/mosaic/framework/skills/ (git fast-export/import) and merging the
rewritten history with --allow-unrelated-histories, so the original commits
with their authors, dates, and messages remain reachable. Blob content is
untouched by the rewrite; tree fidelity was verified blob-sha-for-blob-sha.

This change must be merged with a real merge commit (not squash) or the
history link is destroyed.
2026-08-19 14:33:03 -05:00
jason.woltje fe4fa20309 Merge pull request 'guides: add SEAT-IDENTITY and FLEET-COMMS; harden CODE-REVIEW evidence rules' (#1313) from fred/guides-seat-identity-fleet-comms into next
ci/woodpecker/push/publish Pipeline was successful
Reviewed-on: #1313
Reviewed-by: rev-code-01 <[email protected]>
2026-08-19 15:44:57 +00:00
fred 5e93ef70bd guides: fix the cross-reference direction in SEAT-IDENTITY
ci/woodpecker/pr/ci Pipeline was successful
rev-code-01's non-blocking nit on #1313 round 2. The no-linking-step paragraph
pointed at the bridge explanation as 'described below'; it is above. Now names the
section, which survives further reordering better than a direction word does.

Text-only. Verified with the repo's PINNED prettier (3.8.1 via pnpm-lock.yaml) and
the sanitization gate, both clean.
2026-08-18 19:10:09 -05:00
fred 3884f2de4d guides: address rev-code-01's review of #1313 (B1, B2, S1, S2)
ci/woodpecker/pr/ci Pipeline was successful
All four findings reproduced before fixing. rev-code-01 was right on each.

B2 (blocker, mine). SEAT-IDENTITY provisioning step 4 said to symlink the
framework store entry to the seat slot, while the same file says those bridges
must not be recreated. The same bridge, told both ways, in one document. I
rewrote the resolution and token-location sections when the deploy made them
stale and did not carry the change into the numbered steps. Step 4 is gone and
the file now says explicitly that no provisioning step links the store to the
slot, so the omission cannot read as an oversight.

S1 (mine). The guide claimed the helper "attempts a fleet notification" on
refusal. The shipped helper does no such thing — its only reference to
notification is a comment saying an alert built on the record is best-effort, and
there is no send or wake call anywhere in the file. Now: it writes a durable
record, the record is what exists, and nobody should wait for a notification that
nothing sends. A guide that promises an alert is worse than one that promises
nothing.

S2. Estate-local content removed from files that ship to every estate: the
~/.mosaic/fleet/bin script paths (dead paths elsewhere) and the 2026-08-18 dates,
which dated a specific host's migration rather than describing behavior. The
bridge-removal passage now states the ORDERING that matters — remove bridges only
after a seat-aware helper can reach the slot, never before — which is the part
that transfers.

B1. prettier reformatted all three files. Reproduced the pipeline 2515 failure
locally before and confirmed clean after; the other three guides prettier flags
are untouched by this branch (0 changes vs origin/next) and are pre-existing.

Sanitization gate re-run and passing.

Verified for the record, since I could not verify my own work: rev-code-01
confirmed the no-fallback claim TRUE against helper content on origin/next, and
judged the evidence rules actionable on the grounds that each names an executable
replacement.
2026-08-18 18:51:15 -05:00
fred a3c50d91ca guides: genericize the operator name in SEAT-IDENTITY provisioning
ci/woodpecker/pr/ci Pipeline failed
Pipeline 2514 failed the sanitization gate on 'Jason mints the token into the
seat slot'. The denylist is jarvis|jason|woltje|... and a shipped framework file
must not carry operator identity. My mistake: I generalized the estate paths and
seat names when promoting this guide and did not check the operator name.

Now reads 'the estate operator', with the accompanying rule that an agent does
not ask another agent to mint one either.

Verified by running tools/quality/scripts/verify-sanitized.sh locally rather than
guessing at the pattern: gate passes.
2026-08-18 18:28:37 -05:00
fred 2fd102e6af guides: state the decree, drop the mechanism
ci/woodpecker/pr/ci Pipeline failed
The #1280 prohibition carried an explanation of how the tools misattribute and
why the failure is invisible from inside them. A reader who is not going to use
the tool cannot act on any of it. Same for rule 2's closing clause about what
reviews commonly miss. Both cut to the decree and the corrective action.

Rules 1 and 3-12 keep their trailing sentences: those are corrective actions or
the detail that makes the case recognizable, not justification.
2026-08-18 18:25:47 -05:00
fred efb3c3a10c guides: add SEAT-IDENTITY and FLEET-COMMS; harden CODE-REVIEW evidence rules
ci/woodpecker/pr/ci Pipeline failed
Three guides that existed only as one host's working copy, promoted to framework
templates so every estate gets them. A working copy under ~/.mosaic binds one
host; only a template here binds all of them.

SEAT-IDENTITY.md (new) documents how a seat's git credential is actually
resolved after #1311: identity from MOSAIC_GIT_IDENTITY, then
mosaic.gitIdentity, then the stdin username; host mapped to a store prefix; then
ONE of two stores chosen by whether the seat directory exists, with no
precedence and no fallback between them. A seat with a directory and an empty
slot fails closed rather than reaching the service store, and that is the point.

It also corrects how to find the helper. credential.helper commonly names an
absolute path, so `command -v git-credential-mosaic` answers a different question
than the one git asks, and the two stop agreeing the moment the PATH copy is
removed. Git also tries EVERY configured helper in order, so a fail-closed helper
in front silently hands the request to whatever is configured behind it. The
guide says to read the whole list.

FLEET-COMMS.md (new) documents agent-send.sh: the class table, the addressing
preamble, and the exit codes — including that rc=2 means the text reached the
pane as an unsubmitted draft, so retrying double-sends it. Confirm with
capture-pane instead. It also says to measure the fleet rather than trust
roster.yaml, which on a live host was simultaneously naming a socket that did not
exist, listing seats that were not running, and omitting seats that were.

CODE-REVIEW.md gains an Evidence Discipline section: a green is not a result
until you have shown it could go red, measurement and explanation are separate
sentences, verify by content on the ref that ships rather than by ancestry of a
local sha, and confidence is part of a finding. Plus four shell-measurement rules
earned on #1311, each of which produced a wrong conclusion first — `cmd | tail;
echo rc=$?` reports tail's status, a missed glob under pipefail exits 2 and kills
the run under set -e, nonzero-with-no-output is an environment question before it
is a code question, and `git -C` in a non-repo directory answers from the
enclosing repo.

The estate-specific repository exception that lived in the working copy is not
carried here. The template says an estate may document one, scoped to a named
repository and never precedent for a second.

Both new guides are added to the two routing tables that agents read.
2026-08-18 18:15:50 -05:00
jason.woltje d4d32a80b2 Merge pull request 'git credentials: fail closed, and read a seat's token from its own slot' (#1311) from fred/credential-fail-closed-seat-slots into next
ci/woodpecker/push/publish Pipeline was successful
Reviewed-on: #1311
2026-08-18 22:40:46 +00:00
fred c703cc50eb git-credential-mosaic: escape the escalation record, and stop naming a record that was never written
ci/woodpecker/pr/ci Pipeline was successful
Both defects found in review by rev-code-01 on #1311.

F3 — the JSONL record interpolated every field with a bare %s. An identity comes
from git config or the environment and a cwd is whatever directory git ran in, so
either can contain a quote or a backslash. One such refusal turned the day's spool
into unparseable JSONL, and the operator would only discover it while reading the
record that explains an outage. Fields are now JSON-escaped.

F2 — the diagnostic printed "record: <spool>/<date>.jsonl" unconditionally, but
the record is only written inside the branch where mkdir -p succeeded. When the
spool cannot be created the helper named a file that does not exist, on exactly
the hosts where the escalation was lost. It now reports the real path or says
NOT WRITTEN.

Also: prettier on README.md, which was the format-step failure on pipeline 2508.
It reflowed only the two tables this branch added.

Tests: cases 14 and 15 cover both. Verified discriminating — against the previous
helper with these same tests, case 14 fails with the unparseable record printed
and case 15 fails on both assertions; against this one both pass.

The first draft of case 14 used `ls "$spool"/*.jsonl | head -1`, which under
`set -o pipefail` exits 2 on a missed glob and killed the suite with zero output
— the same silent-nonzero failure rev-code-01 hit from a partial tools/ extraction
and the reason this file exists. Replaced with a glob loop and a comment.
2026-08-18 17:04:55 -05:00
fred 3d2b712355 git credentials: fail closed, and read a seat's token from its own slot
ci/woodpecker/pr/ci Pipeline failed
Two changes to one rule: a credential is resolved from exactly one place,
and an identity that cannot be resolved is refused rather than substituted.

FAIL CLOSED. Both readers ended in an unconditional fall-through to the
shared Gitea account whenever an identity did not resolve. Every seat in a
fleet therefore pushed, opened PRs and filed reviews under one account, and
a record made that way cannot be traced to the agent that made it
afterwards. The fallback now applies only where there is no attribution to
lose: a host with no fleet. Where seats exist, an unresolvable request emits
nothing, exits nonzero, explains itself on stderr, and — in the git helper —
appends a record naming the identity, host, reason and cwd, and no token
value, to ${MOSAIC_CREDENTIAL_SPOOL:-~/.local/state/mosaic-credential-escalations}.

A host runs a fleet when <brain>/fleet/agents exists, which is the signal
packages/mosaic/src/fleet/brain-home.ts already uses to decide a brain is
active, resolved the same way (MOSAIC_BRAIN_HOME, else ~/.mosaic). This is
what keeps the change a no-op for an operator who has not provisioned
per-slot tokens: no fleet directory, shared account, unchanged. It is also
why there is no environment variable to restore the old behavior — one would
reintroduce the substitution being removed.

STORE SELECTION. Both readers hardcoded ~/.config/mosaic/secrets/gitea-tokens,
so a seat's own secrets/ slot was invisible to the framework: a seat could
hold a valid credential and still be served the shared account. The store is
now chosen by what the identity is. An identity with a directory under
<brain>/fleet/agents/ is a seat and is read only from
<brain>/fleet/agents/<id>/secrets/; any other identity is a service identity
and is read from the framework store. There is no precedence between them
and no fallback from one to the other, so a seat with an empty slot is
refused even when a same-named token sits in the framework store. Two copies
of one credential are drift rather than redundancy, and drift surfaces as
the stale copy returning 401, which reads as a revoked token and sends
whoever debugs it somewhere else.

detect-platform.sh is in scope alongside git-credential-mosaic because they
are the two readers of these tokens. Patching only the git helper would make
"one credential, one location" true for push and fetch and false for
pr-create.sh, issue-create.sh and pr-review.sh, which is the harder failure
to notice.

TESTS. The three assertions that pinned the shared-account fall-through are
now fail-closed assertions, and a refusal is checked four independent ways:
nonzero exit, empty stdout, a stderr diagnostic naming identity and host,
and no shared token value anywhere in the output. The exit code alone would
pass against a helper that emitted the credential and then failed. Added:
seat-slot resolution, the no-cross-store-fallback case with a control
proving the framework-store file it declines to read is readable, no-identity
on a fleet host, the fleet gate firing on the default ~/.mosaic and not only
on an injected MOSAIC_BRAIN_HOME, and a cross-host leak check. Both suites
were run against the pre-change code as a control and fail there on exactly
the shared-token emission.

shellcheck is not installed on the authoring host, so the rewritten helper
is unlinted locally and CI is the first lint of it.
2026-08-18 16:19:43 -05:00
fargo 245e0c427d feat(quality-rails): typed evaluator absorbs QC-19/QC-20; verify-release wiring (RI-3-002, #1275) (#1308)
ci/woodpecker/push/publish Pipeline failed
2026-08-18 17:54:47 +00:00
jarvisandfargo ff45f7b5d0 docs(ri-050): forge fail-closed docs + TASKS status catch-up (#1275) (#1299)
ci/woodpecker/push/publish Pipeline failed
Co-authored-by: Jarvis <[email protected]>
2026-08-18 16:00:36 +00:00
jarvisandfargo 64350892e7 docs(ri-050): RI-3-001 complete quality-rails probe inventory (#1275) (#1302)
ci/woodpecker/push/publish Pipeline was canceled
Co-authored-by: jarvis <[email protected]>
2026-08-18 15:59:34 +00:00
jason.woltjeandjarvis 6e9df3c640 fix(doctor): greenfield brain lock-in note (fred's #1301 follow-up, #1288) (#1307)
ci/woodpecker/push/publish Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
2026-08-18 07:57:37 +00:00
jarvis f5ba042dfa test(ri-050): RI-1-002 publish-gate negative controls (#1275) (#1305)
ci/woodpecker/push/publish Pipeline failed
2026-08-18 05:57:06 +00:00
jarvis 7c7dab3898 feat(ri-050): RI-5-001 typed freshness states and stale-safe Mission Control surfaces (#1275) (#1300)
ci/woodpecker/push/publish Pipeline was canceled
2026-08-18 05:56:58 +00:00
fargoandjarvis d92de53399 feat(prd): one transitional PRD authority — RI-4-001 (#1275) (#1294)
ci/woodpecker/push/publish Pipeline was canceled
Co-authored-by: fargo <[email protected]>
2026-08-18 05:56:51 +00:00
mos-dt-0andjarvis d7e303d3c0 fix(macp): fail-closed typed gate states — RI-2-002 (#1275) (#1293)
ci/woodpecker/push/publish Pipeline was canceled
Co-authored-by: mos-dt-0 <[email protected]>
2026-08-18 05:56:38 +00:00
jarvis 726d2ad3a2 fix(ri-050): forge fails closed without providers; explicit typed simulation (#1275) (#1278)
ci/woodpecker/push/publish Pipeline was canceled
2026-08-18 05:52:45 +00:00
jason.woltjeandjarvis e4ee1acf24 feat(doctor): brain-home fleet-state check (#1298 follow-up) (#1301)
ci/woodpecker/push/publish Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
2026-08-18 05:26:01 +00:00
jarvis 5c5a25e4de fix(ci): image pushes read the registry secrets that exist (#1275) (#1306)
ci/woodpecker/push/publish Pipeline failed
Squash-merged by topher (jarvis principal) via break-glass API path (wrapper main-only gap, documented). Gates: CI 2492 green at head e19013ed, review 181 APPROVED (fred) at pinned head. Diagnostic merge: the push pipeline now exercises kaniko with the REGISTRY_* secrets - valid creds yield the first fully green gated publish; invalid yield an explicit 401.

Co-authored-by: Jarvis <[email protected]>
2026-08-18 05:02:23 +00:00
jarvis 7669321ea2 test(gateway): cross-user-isolation cleanup honors dbAvailable — unblocks gated publish verify (#1275) (#1304)
ci/woodpecker/push/publish Pipeline failed
Squash-merged by topher (jarvis principal) via break-glass API path (wrapper main-only gap, documented in #1275 log). Gates: CI 2487 green at head 81f500bd, review 180 APPROVED (fred) at pinned head. Unblocks gated publish: verify's no-DB path now skips cleanly.

Co-authored-by: Jarvis <[email protected]>
2026-08-18 04:24:48 +00:00
jarvis d8e0aec950 feat(ri-050): bind next publication to exact-commit terminal verification — RI-1-001 (#1275) (#1277)
ci/woodpecker/push/publish Pipeline failed
Squash-merged by topher (jarvis principal) via break-glass: pr-merge.sh hard-codes main-only merge targets and cannot express this repo's next trunk. Gates: CI 2476 green at head 46784c8d, review 177 APPROVED (fred) at pinned head. First gated publish: every publish step now depends on verify-release at the exact commit.
2026-08-18 03:57:43 +00:00
jarvis 49d6136b02 docs(ri-050): bootstrap release-integrity workstream for 0.0.50 (#1275) (#1276)
ci/woodpecker/push/publish Pipeline was canceled
Squash-merged by topher (jarvis principal) via break-glass: pr-merge.sh hard-codes main-only merge targets and cannot express this repo's next trunk. Gates: CI 2475 green at head 758659dd, review 176 APPROVED (fred) at pinned head.
2026-08-18 03:57:27 +00:00
jason.woltjeandjarvis a80bae950d feat(fleet): brain-home split — fleet state under ~/.mosaic, templates stay config-home (#1298)
ci/woodpecker/push/publish Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
2026-08-18 03:23:15 +00:00
jason.woltje 8199261caa Merge pull request 'fix(ci): unwire test-start-agent-session.sh, restore its signed exclusion — unblocks every PR on next' (#1270) from fix/1269-ci-chain-unblock into next
ci/woodpecker/push/publish Pipeline failed
Reviewed-on: #1270
2026-08-17 20:44:59 +00:00
fred 57a2f2b40e docs(ci): point the exclusion at tracking issue #1271, not the closed first filing
ci/woodpecker/pr/ci Pipeline was successful
The first PR for this change was filed under the retired mos-dt-0 principal
(pr-create.sh has no --login flag and find_tea_login_for_host returns the first
host match) and was closed and refiled as #1270. That left in-tree references
pointing at a closed duplicate PR rather than at the burn-down issue, which is
the wrong target for them anyway: the open design question belongs on #1271.
2026-08-16 18:03:02 -05:00
fred 93c1de51e1 fix(ci): unwire test-start-agent-session.sh, restore its signed exclusion (#1269)
ci/woodpecker/pr/ci Pipeline was canceled
The `test` step has failed on every `next` pipeline since #1017 on exactly one
assertion, and it is the same one on unrelated PRs:

    FAIL: host provides 'pi' in the system path; missing-binary cases are not
    measurable here            (framework/tools/fleet/test-start-agent-session.sh:103)

Measured 2026-08-16 across pipelines 2444 (#1256), 2438 (#1240) and 2441
(#1017-quality): exactly one FAIL line in each full log, identical, this line.
Control `zzz-not-present-zzz` -> 0 on all three.

Cause. #1241 (5c35a250) added the guard: the suite shims fake mosaic/pi/npm into
$FAKE_BIN, but the constructed PANE_PATH always ends in the real system path, so
on a host that installs those binaries the missing-binary cases cannot be
measured and a green run would mean nothing. The guard says so instead of
passing. Its own pipeline 2430 was green only because the suite was CI-excluded
at the time, so the guard had never run in CI. #1017 (c56483eb) then enumerated
it and dropped the exclusion. The CI image installs
@earendil-works/[email protected].1 on purpose, so the precondition is
unsatisfiable there. Both commits are mine.

The guard is correct and is not being softened. A check that cannot measure its
property and reports success is the failure mode this repo has been cataloguing
all week; the error was wiring the suite into an image that violates its
precondition, so the wiring is what gets reverted.

Second effect, which is the reason this cost a day rather than an hour:
test:framework-shell is one && chain and this sat at position 44 of 48, so
glpi/test-list-http-status.sh, orchestrator/test-board-roll.sh,
woodpecker/test-ci-wait-exit-matrix.sh and _scripts/test-fleet-transport-check.sh
have not run at all since the merge. The pipeline reported one failure, never
"one failure plus four unrun". All four are green when run directly on
sb-it-1-dt, so the mask hid nothing broken -- but that is a local result on one
host, not a CI-image result.

Verification, with controls:
- enumeration guard OK (population 52, enumerated 36, signed-excluded 16).
- control A, exclusion line removed while unwired -> FAIL UNENUMERATED.
- control B, exclusion line kept while rewired -> FAIL CONTRADICTORY EXCLUSION.
  The gate discriminates in both directions, so its OK is load-bearing.
- the four formerly-masked suites: rc=0 each, run directly.
- the full chain cannot be run to completion on sb-it-1-dt: it stops earlier, at
  the lease-broker Invariant R test, because this host carries the quarantined
  operator-global pi 0.84.2 against a measured 0.84.1. That is host-specific and
  out of scope here -- CI pins 0.84.1, and the single FAIL line in those three
  pipelines proves positions 1-43 passed there.

Burn-down is to control the tail of PANE_PATH inside the test, not to remove pi
from the image. Recorded in the exclusion reason and in #1269.
2026-08-16 17:58:49 -05:00
fred 476db12b92 Merge pull request 'fix(fleet): tell the operator when the fleet transport is missing (#1240)' (#1245) from fix/1240-fleet-transport-check into next
ci/woodpecker/push/publish Pipeline failed
Reviewed by scooby via git comms (terminal ACK 32d986). Merge directed by Jason 2026-08-16. Conflicts from #1229 and #1252 resolved on the branch by a pi seat; pre-merge gate verified: tools/install.sh=5d28f773, framework/install.sh=1578c33b, test:framework-shell=48 links with both #1252 and #1245 suites present.
2026-08-16 18:12:33 +00:00
fred 5198c3f198 merge next into fix/1240-fleet-transport-check
ci/woodpecker/pr/ci Pipeline failed
Resolves conflicts from #1229 (tools/install.sh node provisioning) and #1252
(package.json test:framework-shell). tools/install.sh resolved to the reviewed
composite blob 5d28f773; package.json resolved as a union so both #1252's four
suites and #1245's transport-check suite run (48 links).
2026-08-16 13:11:31 -05:00
fred 19ac0a02d7 Merge pull request 'test(#1017): wire in four CI-fit shell suites, drop their signed exclusions' (#1252) from fix/1017-wire-start-agent-session into next
ci/woodpecker/push/publish Pipeline was canceled
Reviewed by scooby via git comms (no mosaicstack principal on fomo-lin; review is the comms record, terminal ACK 32d986). Merge directed by Jason 2026-08-16. Part of the five-PR greenfield composite verified E2E on two independent bare boxes.
2026-08-16 18:06:53 +00:00
fred 6d9387c857 Merge pull request 'fix(fleet): fail the agent launcher when the pane cannot survive (#1241)' (#1244) from fix/1241-launch-failure-visible into next
ci/woodpecker/push/publish Pipeline was canceled
Reviewed by scooby via git comms (no mosaicstack principal on fomo-lin; review is the comms record, terminal ACK 32d986). Merge directed by Jason 2026-08-16. Part of the five-PR greenfield composite verified E2E on two independent bare boxes.
2026-08-16 18:06:50 +00:00
fred 14cb9c6a1e Merge pull request 'fix(fleet): let ps/install work on a roster-v2 fleet, and refuse add/remove honestly (#1237 piece A)' (#1243) from fix/1237-fleet-v2-dispatch into next
ci/woodpecker/push/publish Pipeline was canceled
Reviewed by scooby via git comms (no mosaicstack principal on fomo-lin; review is the comms record, terminal ACK 32d986). Merge directed by Jason 2026-08-16. Part of the five-PR greenfield composite verified E2E on two independent bare boxes.
2026-08-16 18:06:35 +00:00
fred b5b322f80d Merge pull request 'fix(installer): pin umask and set the 0700 modes the fleet boundary requires (#1236)' (#1242) from fix/1236-installer-dir-modes into next
ci/woodpecker/push/publish Pipeline was canceled
Reviewed by scooby via git comms (no mosaicstack principal on fomo-lin; review is the comms record, terminal ACK 32d986). Merge directed by Jason 2026-08-16. Part of the five-PR greenfield composite verified E2E on two independent bare boxes.
2026-08-16 18:06:21 +00:00
jason.woltje e4674709be Merge pull request 'fix(installer): make a greenfield install actually work — node bootstrap, PATH, wizard profile' (#1229) from fix/installer-path-and-node into next
ci/woodpecker/push/publish Pipeline was canceled
Reviewed-on: #1229
2026-08-16 18:01:07 +00:00
fred c56483eb1b test(#1017): wire in four CI-fit shell suites, drop their signed exclusions
ci/woodpecker/pr/ci Pipeline failed
check-test-enumeration.sh signed four suites as 'likely CI-fit; #1017 burndown'.
Measured all four: each passes standing alone, and each still passes with tmux
removed from PATH entirely (test-start-agent-session.sh writes its own tmux shim
into a fake bin dir, so it never needed the real binary).

Red-first: removing the four exclusion lines makes the guard report exactly four
UNENUMERATED failures. Appending the four to test:framework-shell returns it to
OK, with in-population enumerated going 32 -> 36 and signed exclusions 19 -> 15.

Refs #1017
2026-08-16 01:14:03 -05:00
fred 5c35a250de test(fleet): name what the pane-boundary case's binary check rides on (#1241)
ci/woodpecker/pr/ci Pipeline was successful
Review finding from scooby. This case does not use run_start, so
install_pane_binaries' symlinks land under a home its launcher never consults
(HOME is the trusted parent here). It resolves mosaic and pi through
MOSAIC_RUNTIME_BIN=$FAKE_BIN instead. Valid path, valid green — and a trap for
anyone who later drops that env var believing the symlinks cover it, which
would break the #1241 binary check rather than exercise it.

Comment only; no behavior change. Harness rc=0.

Refs #1241.
2026-08-16 00:21:13 -05:00
fred 10a1f82031 test(fleet): cover the pane-pid-unresolved branch this PR shipped (#1241)
ci/woodpecker/pr/ci Pipeline was canceled
Review finding from scooby: this PR added a failure branch the harness
structurally could not reach. The fake tmux answered `has-session` only for
`=_holder:0.0`, so every non-holder agent landed in the session-is-gone branch
no matter what — the `elif` (tmux still reports the session, no pane PID after
the retries) had zero coverage and no way to get any.

That is the same shape as the bug this PR exists to fix, one layer down: a code
path shipped green where the gate that should measure it cannot. Less severe,
because the branch fails closed at exit 69 rather than reporting success — but
"the harness can't reach it" is the sentence that precedes the next silent
regression, so it gets closed here rather than filed.

`MOSAIC_TEST_HELD_SESSIONS` lets a case name targets the shim should also
answer for. It answers them only AFTER `new-session`, and that detail is the
whole trick: the launcher asks `has-session` about the same name twice — once
at line 255 where a yes means "already running, exit 0", and once at 417 where
a yes means "the session survived". A shim answering yes to both short-circuits
at the first and never reaches the branch under test. It would have looked like
coverage while measuring the idempotency path.

Both failure modes were measured, not reasoned about:
- toggle absent (the old shim): `code=pane-did-not-survive` — the case lands on
  the wrong branch, which is exactly the unreachability being reported.
- toggle answering unconditionally: launcher exits 0 via the idempotency
  short-circuit — "launcher reported success over a session with no resolvable
  pane PID".
- toggle gated on new-session: `code=pane-pid-unresolved`, exit 69.

The case also asserts the diagnostic is not `pane-did-not-survive` and does not
mention the heartbeat, so the two pane faults cannot collapse into one message.

Gates: bash -n · launcher harness rc=0 · test-fleet-units.sh (real tmux) rc=0 ·
fleet specs 342 passed.

Refs #1241.
2026-08-16 00:19:25 -05:00
fred b61789fe26 fix(fleet): tell the operator when the fleet transport is missing (#1240)
ci/woodpecker/pr/ci Pipeline was successful
`mosaic fleet --help` reads "Manage the local Mosaic tmux fleet" and every
roster the CLI scaffolds sets `transport: tmux`, but neither `tools/install.sh`
nor `tools/_scripts/mosaic-doctor` contained the string "tmux" at all. A
greenfield host therefore came out of the installer able to install a fleet,
start a fleet, and run no seat, with `mosaic fleet ps` as the operator's first
and only signal.

Measured on mosaic-sbx-dev (Debian, no tmux, framework installed): `mosaic-doctor`
reported 11 warnings and not one of them named the reason no seat could launch.

The installer gets a warning, not a `require_cmd` hard failure: tmux is required
by the fleet, not by mosaic. Hosts that install this to run `mosaic claude` and
never scaffold a roster are common, and failing their install over a binary they
do not need would be wrong. The check runs in `--check` mode too — "what is the
state of this host" is the question `--check` is asked.

Both checks read the roster's own `transport:` rather than assuming tmux, so a
host declaring something else is pointed at the binary it actually needs instead
of at the wrong package.

The two implementations are deliberately parallel and each carries a comment
pointing at the other. They are separate because the installer must answer this
before the framework's own scripts are guaranteed to be on disk. One harness
drives BOTH from the shipped text — the functions are extracted from the scripts
by awk rather than copied — so the pair cannot drift silently, and the test
cannot keep passing after the shipped copy changes.

The harness is wired into `test:framework-shell`. Without that it would have
tripped the #1017 enumeration guard as UNENUMERATED, which is the guard doing
its job: a check nothing runs is not a check.

Evidence:
- red: the harness fails against origin/next ("could not extract
  fleet_declared_transport"); `grep -ci tmux` on both files at origin/next = 0.
- green on real hosts, all four branches:
  - dev (no tmux, no roster)  -> WARN naming tmux, points at `mosaic fleet init`
  - dev (no tmux, v2 roster)  -> WARN naming the roster, points at `mosaic fleet start`
  - dev installer --check     -> WARN saying start "reports success and no seat comes up"
  - canary (tmux present)     -> `[OK] Fleet transport available: tmux` under --verbose,
                                 silent by default (pass() is verbose-gated), installer silent
- harness green on node:24-alpine/busybox, the CI base image.
- `bash -n` x3, `pnpm typecheck` 45/45, fleet specs 342 passed,
  enumeration guard OK, its self-test OK, prettier clean.

Refs #1240. Upstream of #1237/#1243 and #1241/#1244: a correct fix for either of
those still leaves this host with no live seat.
2026-08-16 00:15:50 -05:00
fred 61a907a12f fix(fleet): fail the agent launcher when the pane cannot survive (#1241)
ci/woodpecker/pr/ci Pipeline was successful
`mosaic fleet start` returned 0 over three dead panes. The launcher knew,
and said the wrong thing at the wrong severity to the wrong layer.

The pane runs `mosaic yolo <runtime>` under PANE_PATH with a cleared
environment. When that binary is absent the pane dies in under a second,
tmux destroys the session, and the diagnostic goes with it. The launcher
then found no PANE_PID, printed a WARNING about the *heartbeat sidecar*,
and exited 0 — so systemd logged "Finished ... successfully" and
`fleet start` reported success. `fleet ps` was the only component telling
the truth.

Two changes, both in start-agent-session.sh:

1. Before any effect, resolve `mosaic` and the roster's runtime against
   PANE_PATH — the pane's own view of the path, not the launcher's.
   `mosaic yolo <runtime>` calls checkRuntime(runtime) and looks for a
   binary named exactly like the runtime, so this asks the same question
   the pane will ask a moment later, while an operator can still see the
   answer. Absent binary -> exit 69, code=missing-binary, no session
   created.

2. Replace the dead-pane WARNING+exit-0. An absent session one second
   after new-session is a runtime that died on startup, not a heartbeat
   problem -> exit 69, code=pane-did-not-survive, with the command to run
   by hand to see why. A present session with no pane PID after five
   attempts -> code=pane-pid-unresolved. Neither branch kills the
   session; destroying a possibly-live pane on a guess is worse than
   leaving it for inspection.

Exit 69 (EX_UNAVAILABLE) is deliberate: the 64s already in this file mean
the projection was bad, and here the data is fine and the host is not
ready. Callers separate the cases by `code=`, the same way fail_env's
codes share 64.

This propagates for free. `fleet start` calls runChecked() for the holder
and each agent, and runChecked throws on non-zero, so layers 4 and 5 stop
lying without a TypeScript change. Two adjacent defects are left for a
follow-up issue rather than widened into this diff: the per-agent loop
aborts on the first failure instead of attempting all and reporting an
aggregate, and runChecked's bare throw surfaces the launcher's message
under a Node unhandled-rejection stack trace because program.parse() is
synchronous.

Tests:

- test-start-agent-session.sh gains three cases: `mosaic` absent from the
  pane path, the runtime absent from the pane path, and a pane that does
  not survive. Each was verified individually red against the unmodified
  origin/next launcher.
- The two cases asserting a valid launch now supply a pane PID. Until now
  the suite's one success path was itself a dead pane the launcher
  reported as fine.
- The harness fakes `npm` so PANE_PATH stops depending on whatever the
  host has installed, and fails loudly if the host provides `mosaic` or
  `pi` in the system path, where the missing-binary cases would not be
  measurable at all.
- test-fleet-units.sh gains a `pi` shim in its runtime bin. The real-tmux
  harness named `pi` in its roster and never installed it; the new
  preflight caught it.

Refs #1241
2026-08-15 23:56:53 -05:00
fred 6f5b4c3dc1 fix(fleet): restore ConditionPathExists dropped by my own red-check
ci/woodpecker/pr/ci Pipeline was successful
Self-inflicted and worth recording rather than quietly amending.

To prove the new tests were red without the fix I ran
`git checkout origin/next -- <fleet.ts> <[email protected]>`. That writes
the *index*, not just the working tree. Copying my versions back afterwards
restored the working tree only, so the unit file sat staged-as-origin/next and
modified-in-tree, and the next commit (67f5014c) committed the index — silently
removing the ConditionPathExists line that 463745e3 had added.

Nothing caught it. The spec reads the file from the working tree, so it stayed
10/10 green against a HEAD that no longer had the guard. Found by reading
`git status` after the push, not by any gate.

Verified by content, not by assumption:
  origin/next  0 occurrences
  463745e3     1
  67f5014c     0   <- the regression
  this commit  1

Refs #1237
2026-08-15 23:35:54 -05:00
fred 67f5014cc0 fix(fleet): refuse v2 add/remove cleanly, and pin the Condition's effect
Two follow-ups from the canary red->green run and scooby's review.

1. The v2 refusal in `add`/`remove` was a bare `throw`, which reaches the CLI
   top level uncaught and prints the guidance under a Node stack trace. The
   message *is* the point of the refusal, so it now goes through
   `command.error()` — the same clean path the roster-config error uses.
   Caught on canary, not in review: the unit tests asserted the message text
   and passed either way.

2. The unit-template test asserted only that ConditionPathExists is present.
   Presence is not effect. Added two tests for the parts that can drift in
   code while that assertion still passes: the condition resolving to exactly
   the file the fleet writes (%h/%i rendered against a real install), and the
   launcher genuinely failing on an absent generated env (exit 64,
   `missing-file`) — which is what makes the condition load-bearing rather
   than decorative.

systemd is not available in the suite, so the effect itself was measured on
canary (2026-08-16), roster v2 generation 3:

  with the condition:    start rc=0, Result=success, ConditionResult=no,
                         journal "skipped, unmet condition check"
  condition removed by
  drop-in, nothing else: start rc=1, Result=exit-code, ExecMainStatus=64,
                         unit failed, "agent environment rejected: missing-file"

Canary red->green for the three commands, same v2 roster, side by side:

  fleet ps               0.0.50-next.2413 rc=1  ->  branch rc=0 (3 agents listed)
  fleet install          0.0.50-next.2413 rc=1  ->  branch rc=0
  fleet remove <name>    0.0.50-next.2413 rc=1  ->  branch rc=1, refusal naming
                                                    delete + apply

All three previously failed with "Fleet roster has unknown field(s):
generation." The #791 negative was measured too: the six existing
*.env.generated files were untouched by `install` (mtimes 20+ minutes older
than the run).

Gates: typecheck 0, eslint 0, prettier clean, fleet specs 382 passed, new spec
10/10 with the fix and 9/10 red against origin/next (the 10th passes there for
an unrelated reason and is annotated as such). Full suite: only
mutator-gate.acceptance.spec.ts fails, pre-existing on origin/next.

Still true and still worth saying: a correct fix here shows install rc=0 and
start rc=0 and STILL no live seat. #1240 (tmux absent) is upstream, #1241
(start reports lifecycle-complete over dead panes) and the missing agent
runtime are downstream.

Refs #1237
Reviewed-by: scooby (by git comms; cannot file a Gitea review from fomo-lin)
2026-08-15 23:34:35 -05:00
fred 463745e314 fix(#1237): let ps/install work on a roster-v2 fleet, and refuse add/remove honestly
On a roster-v2 fleet, `ps`, `install`, `install-systemd`, `add` and `remove`
all failed in the v1 parser. The consequence was that a greenfield v2 box could
never get its unit templates placed, so nothing downstream could start.

The read-only commands get a narrow version-agnostic view of the roster
(version, socket name, holder session, and per agent name/alias/runtime).
This is deliberately not a v2 -> v1 downshift. A downshifted FleetRoster would
be accepted by generateAgentEnvValues, which would make a third writer of
fleet/agents/<name>.env.generated through the v1 mapping and break the #791
single-SSOT invariant that projectRosterV2AgentGeneratedEnv is documented to
hold. The view is too small to write a roster or an env file back from, so that
misuse is unavailable rather than merely discouraged.

So on a v2 roster `install` places the tool files and the unit templates,
enables the units, and writes no generated env at all. Env belongs to `apply`
and `regen`, both already v2-native.

That change alone would have traded an init-time failure for a boot-time one.
`install` enables mosaic-agent@<name>.service (WantedBy=default.target) without
starting it, so a reboot between `install` and the first `apply` would run
ExecStart against an absent env file and fail every seat unit, further from its
cause. The unit template now carries

  ConditionPathExists=%h/.config/mosaic/fleet/agents/%i.env.generated

which skips an enabled-but-unconfigured unit cleanly and starts it on the next
start once the reconciler has written env. On v1 it is a no-op, since v1
`install` writes env itself. Found in review by scooby.

`add` and `remove` are not routed to `create` and `delete`. They are different
operations: the v1 pair edits the roster and drives systemd, the v2 pair is
documented as changing desired state without runtime actions. `add` also
collects four fields where a v2 agent requires eleven, so routing it would mean
inventing an operator's provider, alias, reasoning and tool policy. On v2 both
now fail with the real two-step sequence instead.

Tests: 8 new, 7 of which are red before this change. Includes the greenfield
case scooby asked for — `ps` on a fresh v2 install with nothing running is rc=0
and lists every agent stopped, since that is the command an operator runs to
find out why there is no seat.

Note for anyone verifying this: a correct fix here shows `install` rc=0 and
`start` rc=0 and still no live seat. #1240 (tmux absent) is upstream, #1241
(start reports lifecycle-complete over dead panes) and the missing agent
runtime are downstream. A dead pane after this change is not a regression here.

Refs #1237, #791, #1240, #1241
2026-08-15 23:24:24 -05:00
fredandClaude Opus 5 03eda02c20 fix(installer): warn on a failed credentials/ chmod instead of swallowing it
ci/woodpecker/pr/ci Pipeline was successful
scooby's review flag 1 on #1242. The other three chmods warn; this one was
`|| true`. It is the one directory holding secrets, so a chmod that fails
silently there is the failure most worth a line in the output.

Comment-and-warn only. No behaviour change on the success path.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01WYgWocp36goy8hj2ui6ps1
2026-08-15 22:40:47 -05:00
fredandClaude Opus 5 3b4055017e fix(installer): pin umask and set the 0700 modes the fleet boundary requires (#1236)
ci/woodpecker/pr/ci Pipeline was canceled
A greenfield install cannot run `mosaic fleet init --write`. It fails with
`unsafe-permissions` on an unnamed `(directory)` and an unhandled Node throw,
and every mutating `mosaic fleet` command fails the same way. Measured on a
reverted-to-greenfield sandbox VM at CLI 0.0.50-next.2413: `~/.config/mosaic`,
`fleet/` and `credentials/` all land at 0775, and 1735 directories under the
framework root carry `mode & 022`.

Two independent causes, and fixing either one alone leaves it broken.

1. The installer inherited the caller's umask. Debian/Ubuntu ship 002, so every
   `mkdir -p` produced 0775. Fedora/RHEL ship 022 and produced 0755. The
   product therefore worked or did not depending on the operator's login shell,
   with nothing in the install output distinguishing the two. 022 is already
   what this script assumes it produces — `make_durable_snapshot` restores the
   ambient umask specifically so "every later sync copy and new framework dir"
   gets 0644/0755 — so pin it rather than inherit it.

2. Even at a correct 0755, three directories are rejected. The fleet code
   guards its managed paths with two masks in two languages:
   `assertPrivateManagedDirectory` (fleet-reconciler.js, `mode & 0o077`) covers
   MOSAIC_HOME and `fleet/` and runs before the roster lock is taken;
   `assert_private_directory` (tools/fleet/start-agent-session.sh, `mode & 077`)
   covers `fleet/agents` and runs before a pane is spawned. Their laxer
   siblings use `mode & 0o022` and accept 0755. The strict mask wins, so the
   installer states 0700 outright instead of hoping a umask implies it.

The `find -perm /022 -exec chmod go-w` sweep repairs a tree installed before
this change, which the umask alone cannot reach. It strips group/other WRITE
only — never read or execute — and is scoped to directories, so it corrects the
boundary violation without changing who may traverse or read anything. It is
not sufficient for `fleet/agents`: stripping write from 0755 yields 0750 and
`mode & 077` is still non-zero, which is why that path gets its own chmod.

Reported as #1236. The `fleet/agents` half was found by scooby reading
start-agent-session.sh; the umask framing is theirs too — my first report
blamed the distro rather than the umask.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01WYgWocp36goy8hj2ui6ps1
2026-08-15 22:29:48 -05:00
fred 07373ede4d docs(install): record the two trust/portability assumptions in install_node
ci/woodpecker/pr/ci Pipeline was successful
Comment-only, no behaviour change. Both raised by scooby in the #1229 review
as non-blocking findings worth writing down rather than fixing here.

F-A: the SHASUMS256.txt check gives integrity, not authenticity. TLS to
$NODE_DIST_BASE is the whole trust root, and MOSAIC_NODE_DIST_BASE widens it
to any mirror with no signature backstop. GPG-verifying SHASUMS256.txt.sig is
filed as its own follow-up so it gets its own review.

F-C: the uname map pulls the glibc build, so musl hosts fail — visibly, via
node_is_suitable, not silently.
2026-08-15 21:50:14 -05:00
fredandClaude Opus 5 fb5bb98a32 Revert "fix(installer): re-link runtime assets after the CLI stage"
ci/woodpecker/pr/ci Pipeline was canceled
This reverts 47e90767. I was wrong: the fix is correct about the cause and
makes the outcome worse.

The acceptance run passed everything I set out to check — greenfield canary
1125, --next --yes, no TTY, rc=0, node v22.23.2 + CLI 0.0.50-next.2413 from a
fresh login shell, and both enforcement hooks wired in ~/.claude/settings.json
where before they were stripped. Then `mosaic doctor` on that same host:

  [ERROR] Lease-enforcement hooks (mutator-gate.py, receipt-observer-client.py)
  are wired in ~/.claude/settings.json, but broker not healthy
  (checkBrokerSupervisorHealth() reports unhealthy). Every gated tool call will
  fail closed and BRICK this agent (see #869).

So the change takes a greenfield host from 'enforcement quietly off, agent
works' to 'enforcement wired, broker absent, agent bricks on the first gated
tool call'. The pre-existing behaviour reaches the safe state for the wrong
reason; this reaches the unsafe state for the right one. Safe-for-the-wrong-
reason still wins.

The real defect is underneath both, and it is not an ordering bug:

  mosaic __link-claude-settings ...   -> rc=0  (leaseEnforcementActivatable:
                                                 activatable, wire the hooks)
  mosaic doctor                       -> ERROR (checkBrokerSupervisorHealth:
                                                 unhealthy, hooks will brick)

Two capability checks, same host, opposite verdicts. And after a complete
install there is no broker supervisor to be healthy: no systemd --user unit
matching lease/broker, nothing under ~/.mosaic but the bootstrapped node, and
no lease or broker script in ~/.config/mosaic/tools/_scripts/. Lease
enforcement cannot be activated on a greenfield host at all, so
leaseEnforcementActivatable() returning true is the thing that is wrong.

Filing that separately. PR #1229 goes back to exactly the four commits scooby
reviewed.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-15 21:42:20 -05:00
fredandClaude Opus 5 47e90767b7 fix(installer): re-link runtime assets after the CLI stage, so greenfield keeps its enforcement hooks
ci/woodpecker/pr/ci Pipeline was canceled
The framework's install.sh ends by running mosaic-link-runtime-assets, which
asks the `mosaic` CLI whether lease enforcement can be activated before
deciding whether to wire the #828 hooks into settings.json. Part 1 (framework)
runs before Part 2 (npm CLI), so on a first install there is no CLI to ask. The
script takes its fail-safe branch, prints a four-line ERROR, and writes
settings.json with mutator-gate.py and receipt-observer-client.py stripped out.

Measured on canary 1125, rolled back to greenfield, `--next --yes`, no TTY:

  framework template ~/.config/mosaic/runtime/claude/settings.json
    mutator-gate.py            1 occurrence
    receipt-observer-client.py 1 occurrence
  installed ~/.claude/settings.json after a clean rc=0 install
    mutator-gate.py            wired: False
    receipt-observer-client.py wired: False

So enforcement ends up off because of the order the two halves install in, not
because of anything about the host. Falsified by running the same script by
hand once the CLI existed: rc=0, both hooks wired: True. The guard's real
verdict on that host was 'activatable' the whole time.

This adds one more pass after Part 2. The script is idempotent (unchanged files
are skipped), so on an upgrade — CLI already present, first pass already
correct — it is a no-op. It deliberately does not pass
--allow-inactive-enforcement: Part 1 does not either, and a repair pass must
not be more permissive than the pass it corrects.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-15 21:38:11 -05:00
fred 00bc602f93 fix(installer): persist the bootstrapped Node on PATH, and stop duplicating PATH lines
ci/woodpecker/pr/ci Pipeline was successful
Two defects found by the second unattended greenfield run on canary (VMID 1125,
rolled back to its greenfield snapshot first).

1. ensure_node() exported the Mosaic-managed Node for the installer process and
   nothing wrote it down. The install finished rc=0, put $PREFIX/bin in
   ~/.profile, and the next login shell found `mosaic` and then died on

       env: 'node': No such file or directory

   The CLI is a Node script, so a CLI on PATH without its runtime is a
   successful install that produces a broken command. persist_node_on_path()
   now writes the runtime's bin dir to the same profile, from both the
   fresh-install and the already-installed-but-not-on-PATH branches.

2. The 'is it already in a shell rc file' guard was a single
   `grep -qslF "$dir" "${rc_files[@]}"` over four paths, most of which do
   not exist on a clean host. Handing grep a missing file makes the exit status
   implementation-defined: GNU grep 3.11 returns 0 when -q already matched an
   earlier file, ugrep 7.5 returns 2 for the missing one regardless. On the 2
   path the caller reads 'not present yet' and appends another PATH line, so
   every re-install grew the profile. Measured: 3 runs produced 3 duplicate
   entries; with the fix, 1.

   path_entry_exists() now tests each file for existence and greps it on its
   own, so the result does not depend on the grep implementation.

The profile-writing body is factored into persist_on_path(), shared by the CLI
prefix and the Node runtime, since both now need identical treatment.

Verified in a scratch $HOME: fresh write, idempotent across three runs, zsh
routes to .zshenv, an unwritable profile warns and survives set -e, and an
already-on-PATH prefix is a no-op that creates no file. Falsified by restoring
the multi-file grep: duplicates return.
2026-08-15 16:07:56 -05:00
fred d0c223bdf9 fix(wizard): write PATH to .profile/.zshenv, never .bashrc
ci/woodpecker/pr/ci Pipeline was successful
getShellProfilePath() preferred ~/.bashrc when it existed, and ~/.zshrc for
zsh. setupPath() in stages/finalize.ts appends the PATH export to whatever
it returns. Debian's default ~/.bashrc opens with

    case $- in *i*) ;; *) return;; esac

so a line appended to the bottom of it never runs for 'bash -lc', for
systemd units, for 'ssh host cmd', or for any agent seat — precisely the
consumers that need the CLI. An install could print its summary and exit 0
while leaving 'mosaic: command not found'. .zshrc has the same problem:
zsh only reads it for interactive shells.

Now ~/.profile, which login shells read and which Debian's copy sources
.bashrc from for interactive shells, so one line covers both. For zsh the
always-sourced file is .zshenv. fish and PowerShell are unchanged.

__tests__/platform/detect.test.ts pins it, including a case asserting that
no shell resolves to an interactive-only rc file. Falsified by inverting
the fix: 5 failed / 1 passed; restored 6/6. Full package suite unchanged at
17 files / 4 tests failing, matching clean origin/next.
2026-08-15 15:54:10 -05:00
fred cc0d24d5c4 fix(installer): bootstrap Node.js on a greenfield host
tools/install.sh required node and npm and installed neither. Measured on a
snapshot-reverted Debian 13 image with no node, npm or git: the run stopped
at `require_cmd node` with "Required command not found: node", exit 1,
nothing installed, and no indication of how to proceed.

Adds ensure_node() to preflight. It fetches an official Node.js release into
$HOME/.mosaic/node, verifies it against that release's SHASUMS256.txt, and
refuses rather than degrades when the entry is missing or the checksum does
not match. sha256sum on Linux, shasum on macOS. .tar.gz over the smaller
.tar.xz because gzip is universally present and xz is not — a minimal image
is the case this exists to handle.

No-op when a suitable node is already on PATH, so it never fights an
operator's nvm/fnm/distro node. MOSAIC_SKIP_NODE_BOOTSTRAP=1 declines the
download and fails with instructions instead.

Inlined rather than factored into a sibling file because this script is
fetched standalone by curl and has nothing to source.
2026-08-15 15:54:09 -05:00
fred 40fecd4d38 fix(installer): put $PREFIX/bin on PATH instead of warning about it
The three duplicated PATH blocks in tools/install.sh only warned, so an
unattended install finished with rc=0 and left `mosaic: command not found`
— there was no operator to read the advice and act on it. Measured on a
greenfield Debian 13 sandbox: `--next --yes` installed
@mosaicstack/[email protected] successfully and the CLI was still
unreachable.

Replaces all three copies with one ensure_prefix_on_path helper that
appends the export to ~/.profile (~/.zshenv under zsh) and is a no-op when
the prefix is already on PATH or already in a shell profile.

Not ~/.bashrc: Debian's default .bashrc returns early for non-interactive
shells, so a line appended there is unreachable to `bash -lc`, systemd
units and agent seats — the consumers that need the CLI.
2026-08-15 15:47:30 -05:00
mos-dt-0 7a6fb024b4 docs: establish canonical documentation architecture (#1210)
ci/woodpecker/push/publish Pipeline failed
2026-08-13 17:56:13 +00:00
mos-dt-0 f82307c4dc fix(lease): raise capability-probe timeout to 10s on both halves (#869) (#1207)
ci/woodpecker/push/publish Pipeline failed
2026-08-13 17:28:00 +00:00
coder2andMos 7102ccb93e docs(tools): index pull request edit wrapper (#1200)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: coder2 <[email protected]>
2026-08-13 14:50:38 +00:00
Mos afdaa6d0e6 framework: make tool discoverability, workspace placement and model tiering mechanical (#1174)
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/push/publish Pipeline was successful
2026-08-13 14:21:22 +00:00
coder3andMos 41749bbd33 fix(framework): detect installed tool drift (#1194) (#1195)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: coder3 <[email protected]>
2026-08-13 10:43:11 +00:00
Mos 120af4e193 feat(git-tools): add pull request edit wrapper (#1080) (#1173)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-08-13 06:28:01 +00:00
shaggyandmos-dt-0 216cd72226 refactor(chat): route browser chat through one runtime (P3 Slice-Zero Task 5) (#1172)
ci/woodpecker/push/publish Pipeline failed
Co-authored-by: shaggy <[email protected]>
2026-08-12 20:11:12 +00:00
mos-dt-0 6a8ce66702 Merge pull request 'feat(lease): verified lease-remediation stack (rebased onto next) — promotion trigger + promote CLI + carve-out + TTL' (#1109) from feat/lease-promotion-and-harness-isolation into next
ci/woodpecker/push/publish Pipeline failed
2026-08-12 03:07:32 +00:00
jason.woltjeandMos 9cd9409089 P3 Slice Zero, Task 4 — replace Web free-text selection with the structured harness catalog (#1170)
ci/woodpecker/push/publish Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
2026-08-12 02:50:18 +00:00
Jason WoltjeandClaude Fable 5 13c70a7a10 test(mutator-gate): keep launch ledger out of the shipped framework tree
ci/woodpecker/pr/ci Pipeline was successful
runRuntimeLaunchEntry set MOSAIC_HOME to the shipped framework root, so
launch-runtime.py appended its launch ledger to
framework/fleet/run/sessions/events.ndjson — polluting the tree that
manifest.spec.ts walks and failing its completeness check in CI.

Point MOSAIC_HOME at the per-entry temp root instead. Nothing in the
launch chain resolves tools via MOSAIC_HOME (entry scripts resolve via
SCRIPT_DIR); the ledger is its only consumer here.

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Dtdjx4Gxude9fwyLezCrhh
2026-08-11 20:51:03 -05:00
dd6357e670 test(skill): install linker asserts harness-home link topology
The two install-linker-compatibility tests still asserted the pre-isolation
behavior (mosaic skill links planted in $HOME/.claude/skills). This branch
deliberately moved the link farm into the mosaic-owned harness homes
($MOSAIC_HOME/.claude/skills) and demoted the base-install dirs to
cleanup-only legacy targets, so the tests now assert the new topology:
the skill links appear under the harness home, foreign links in the legacy
dir are preserved, and no new mosaic link is planted in the base install.

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Dtdjx4Gxude9fwyLezCrhh
2026-08-11 20:51:03 -05:00
Jason Woltje 709a23d08c feat(mosaic): mechanically authorize lease promotion 2026-08-11 20:51:03 -05:00
Jason WoltjeandClaude Opus 4.8 239a2a93f1 test(lease): #1124 regression uses node pane command (real field topology per scooby)
The mosaic wrapper makes pane_current_command=node (RUNTIME_ACCEPTABLE_COMMANDS.claude=['claude','node']); the walk matters precisely in that no-shell-wrapper case. Match reality.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_013SAYFkRhQfhguY7AHfiUC8
2026-08-11 20:51:03 -05:00
Jason WoltjeandClaude Opus 4.8 ea1f058022 fix(lease): resolve lease session id from the claude child, not the tmux pane pid (#1124)
The launcher runs the runtime as a spawnSync CHILD of node(mosaic) (deliberate,
per launch.ts:99 — parent survives to propagate signals), so
MOSAIC_LEASE_SESSION_ID lives on the claude child, not the pane's root pid. The
transport read only pane.pid's /proc/environ and returned RESOLVE_FAILED for
every real 'mosaic claude' seat. Now BFS the pane's process subtree (bounded,
injectable children-reader) and read the first descendant that carries a valid
lease id; fail-closed if none. Unit tests now exercise the real walk (pane=node
without lease -> child=claude with lease) rather than mocking the resolution.

Found by scooby greenfield E2E on fomo-lin with proc-level evidence.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_013SAYFkRhQfhguY7AHfiUC8
2026-08-11 20:51:03 -05:00
Jason Woltje 1fde450ff1 test(lease): align mutator carve-out acceptance 2026-08-11 20:51:03 -05:00
Jason Woltje c136baa052 fix(mosaic): bound promotion transport delivery 2026-08-11 20:51:03 -05:00
Jason Woltje 4f7f6b3281 feat(mosaic): add correlated lease promotion CLI 2026-08-11 20:51:03 -05:00
Jason Woltje 77edb0dea2 feat(lease): add single-turn Claude promotion trigger 2026-08-11 20:51:03 -05:00
Jason WoltjeandClaude Fable 5 3676180ae8 fix(lease): raise lease TTL 300s -> 3600s
MAX_LEASE_TTL_SECONDS (daemon cap+default) and DEFAULT_TTL_SECONDS
(lease_promote client) both move to 3600. The 5-minute TTL made
gated-by-default sessions unusable (re-promotion mid-task); 1 hour
matches a working session. Full test:framework-shell RC=0.

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013SAYFkRhQfhguY7AHfiUC8
2026-08-11 20:51:03 -05:00
Jason Woltje 0e938b66ed fix(lease): ignore benign observer idle replies 2026-08-11 20:51:03 -05:00
Jason Woltje f0fef26eb7 fix(lease): constrain read-only tool carve-outs 2026-08-11 20:51:03 -05:00
Jason Woltje c9bccd4aae test(lease): assert pi carve-out capability 2026-08-11 20:51:03 -05:00
Jason Woltje 8ef2e5b91d test(lease): distinguish pi probe timeouts 2026-08-11 20:51:03 -05:00
Jason Woltje 4cab6c09fe test(lease): enforce read-only tool invariant 2026-08-11 20:51:03 -05:00
Jason Woltje 239fc6d03c docs: measure pi tool registry 2026-08-11 20:51:03 -05:00
Jason WoltjeandClaude Fable 5 d085182dc1 test: close W-0R review findings — assert the omission notice, skip chmod simulations under root
The independent W-0R review of 3592b92e passed but left two PLAUSIBLE
findings: the stderr notice for a legitimately-omitted operator source was
claimed and never asserted (a silent omission is the original defect in
miniature), and the chmod 0o000 unreadable simulations fail spuriously when
euid==0 (CAP_DAC_OVERRIDE). Falsifier for the new assertion: deleting the
notice block turns the suite red (failures=3); restoring returns green.

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01EHYXhcCQsL3J1Lnm7EraGq
2026-08-11 20:51:03 -05:00
Jason WoltjeandClaude Opus 5 e949fa3767 fix(lease): refuse an incomplete law binding instead of silently shrinking it
build_construction skipped any normative source it could not read
(`except OSError: continue`) and promoted whatever remained. That is not a
degraded binding, it is a forged smaller one: the broker recomputes h_source /
h_payload from the fragments it is SENT (daemon.py:602-616), so an omitted
fragment is internally consistent and PAYLOAD_BINDING_MISMATCH cannot fire. A
partial law promotes exactly like a complete one and nothing downstream can tell
the difference.

Measured before this change, against a seeded home: with only USER.md readable,
the client produced a one-fragment construction with promotion=True. Removing
CONSTITUTION.md, STANDARDS.md or the runtime contract likewise promoted.

The classification mirrors the framework's own file ownership rather than
inventing one:

  * CONSTITUTION.md / AGENTS.md / STANDARDS.md are framework-owned and
    reconciled every upgrade (install.sh FRAMEWORK_OWNED,
    config/file-adapter.ts FRAMEWORK_OWNED_FILES), as is the per-runtime
    RUNTIME.md. Absent => IncompleteBinding. A deployment missing one is broken,
    not minimal.
  * SOUL.md / USER.md are deliberately not seeded by install.sh ("generated by
    `mosaic init`") and TOOLS.md is seeded on first install only, so their
    absence is legitimate. It is reported on stderr, never silent.

Unreadable is handled separately from absent for EVERY source, optional ones
included: a file that will not open is not a file that was never configured, and
collapsing the two is what let a permission change quietly shrink the law.

Also corrects this module's own docstring, which asserted that a VERIFIED lease
means "this agent is running THIS law". It does not. Both sides of the broker's
comparison originate in this client, so it detects corruption in transit and
nothing else. That overstatement is where the belief spread from; the stronger
claim needs the broker re-reading on-disk sources against a manifest the agent
cannot rewrite.

Test: promotion_binding_unittest.py, enumerated in test:framework-shell (the
enumeration guard's population is *test*.sh and does not cover Python, so an
unenumerated test here would simply never run). Falsifier executed: defeating the
guard while leaving the module API intact turns the suite red (12 failures);
restoring it returns green.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01EHYXhcCQsL3J1Lnm7EraGq
2026-08-11 20:51:03 -05:00
Jason Woltje f1761c91be Revert "feat(pi): wire lazy lease promotion into the mutator gate"
This reverts 939f2e04. Keeping the revert rather than dropping the commit,
because the failed attempt is the most useful record on this branch.

The wiring worked mechanically — verified with a live model on sb-it-1-dt: the
receipt was emitted verbatim as a whole message, and the broker token was minted
AND consumed, so observe_receipt and promote_lease both succeeded and the lease
reached VERIFIED.

It failed as a DESIGN, for reasons that are properties of the protocol rather
than of this wiring:

  * It puts control-plane traffic in the user-facing conversation channel. An
    operator asking "what model are you?" received a receipt string instead of an
    answer — the model tried a tool, was blocked, complied with the receipt
    instruction, and in one-shot mode that text turn BECAME the reply. Observed
    twice, non-deterministically.
  * The lease TTL is hard-capped at 300s (MAX_LEASE_TTL_SECONDS; ttl_seconds >
    cap raises INVALID_LEASE_TTL). Measured: allowed at T+0, LEASE_EXPIRED at
    T+310. So the visible cost recurs every five minutes of mutator activity.
  * Model compliance is not guaranteed — one run retried the command instead of
    emitting the receipt.

Any model emission is user-visible, so this is not fixable by better wiring; it
needs a design answer about how promotion is triggered and paid for. That is
under adversarial review (docs/scratchpads/lease-remediation/07-liveness-design-brief.md
in the operator's repo). Promotion triggering will return on its own branch once
that lands.

What remains here is independently sound and unblocked: harness-home isolation,
the immutable launch record, the skills relocation, the promotion client itself
(steps 1/4/5), and the #1087 prefix guard.
2026-08-11 20:51:03 -05:00
Jason Woltje 8109f72cf7 fix(sync-skills): guard the pre-existing prune against an empty prefix (#1087)
prune_stale_links_in_target compared "$resolved" == "$canonical_real/"* while
length-checking only $resolved. If $canonical_real were ever empty the pattern
collapses to == "/"* and matches every absolute path.

The failure is precisely inverted, which is what makes it worth fixing rather
than noting: is_mosaic_skill_name already `continue`s for names that ARE current
mosaic skills, so an empty prefix would delete exactly the FOREIGN symlinks in
every target directory and preserve the mosaic ones. On this host that is 4 base
installs, including codex's own .system entry.

Reported by mos-claude as #1087 after I introduced the same guard in the new
legacy-cleanup path in the previous commit and walked past this instance thirty
lines away. Same defect class, same file, one function apart.

$canonical_real is populated by readlink -f after a mkdir -p, so an empty value
requires readlink to fail — unlikely, but the consequence is deleting operator
symlinks across every harness, which is not a risk worth carrying for one test.
2026-08-11 20:51:03 -05:00
Jason Woltje a0be592d84 feat(pi): wire lazy lease promotion into the mutator gate
Completes the promotion path: the client landed in the previous commit, but
nothing drove step 2 — the model emitting the receipt. This wires it.

LAZY, not at session start. Promotion costs an entire model turn, because the
receipt must be the whole message (hmac.compare_digest, "not a transcript
substring"). Minting at session start would collide with the Constitution's
first-response mode declaration — the two cannot share a message, so requiring
both would be unsatisfiable. Deferring to the first DENIED MUTATOR means the
mode declaration happens first and the receipt gets its own later turn, so no
governance change is needed. A read-only session never pays for promotion at all.

Mechanism: on a MUTATOR_UNVERIFIED denial the tool_call hook mints a challenge
and returns the receipt in the block `reason`, which pi feeds back to the model
as the tool result — the existing injection path already used by
lease-lifecycle.ts. The model emits the receipt as its next message, message_end
ships it to the observer, and the extension then calls observe_receipt +
promote_lease.

Only MUTATOR_UNVERIFIED triggers minting. Other denials (GATE_UNAVAILABLE,
STALE_GENERATION, LEASE_EXPIRED, ANCESTRY_MISMATCH) describe conditions a
receipt cannot fix, and begin_verification revokes before it mints, so minting
there would thrash the broker.

Completion is gated on an EXACT text match against the minted receipt. This is
load-bearing, not defensive: message_end also fires for the message that
CONTAINED the blocked tool call — one turn BEFORE the model answers. An earlier
version completed there, so observe_receipt compared against the wrong text,
failed, and burned the challenge before the model ever emitted it. Matching the
text mirrors the broker's own compare_digest semantics and waits for the right
turn. Confirmed by instrumenting message_end and watching it fire with
pending=yes one message too early.

It never posts the receipt itself. receipt-observer-client.py accepts any
string, so self-posting would satisfy the broker while proving nothing — the
whole point is that a live model echoes a challenge it was given.

Bounded by MAX_PROMOTION_ATTEMPTS: model compliance is not guaranteed (observed
a run where the model retried the command instead of emitting the receipt), so
a non-complying model degrades to today's behaviour — denied mutators — rather
than looping.

Verified with a live model on sb-it-1-dt: receipt emitted verbatim as a whole
message, and the broker token was minted AND consumed, i.e. observe_receipt and
promote_lease both succeeded and the lease reached VERIFIED.

Known limitation: under `pi -p`, the receipt is a text-only turn, which ends the
one-shot loop — so promotion completes but the blocked tool is not retried in
that same invocation. Interactive and durable fleet sessions continue and retry
normally.
2026-08-11 20:51:03 -05:00
Jason Woltje f4a24b693e feat(lease-broker): add the missing promotion client
The enforcement half of the lease broker ships and denies; the promotion half
has no production caller anywhere in the package. Verified across 0.0.48, 0.0.49
and 0.0.50-next.2207: begin_verification / observe_receipt / promote_lease are
invoked only by broker-test-client.ts, the acceptance spec, unit tests, and two
probes under docs/.

Consequence: no lease on any host can reach VERIFIED, so mutator-gate denies
every mutator with MUTATOR_UNVERIFIED via a gate that nothing shipped can
satisfy. Runtimes that enforce the gate in-process (pi, via mosaic-extension's
tool_call hook) are bricked for mutators; runtimes whose gate is wired through a
settings hook escape only when that hook is absent — i.e. by being ungated.

This adds the client. It implements protocol steps 1, 4 and 5:

  1. begin_verification  -> mint a challenge, return the exact receipt text
  2. the MODEL emits that text verbatim as its entire latest message
  3. the runtime adapter ships that message to the observer socket
  4. observe_receipt      -> PENDING_PROMOTION
  5. promote_lease        -> VERIFIED

Step 2 is deliberately NOT implemented here, and that is the point.
is_verbatim_receipt uses hmac.compare_digest against the exact minted string —
explicitly "not a transcript substring" — which makes promotion a LIVENESS
PROOF: it requires a live model that received the challenge in its context and
echoed it exactly.

receipt-observer-client.py will post ANY string as the latest assistant message.
A promotion client that posted its own receipt would satisfy the broker while
proving nothing — a gate-disabler indistinguishable from a working fix unless
someone specifically looks. Emitting the receipt therefore belongs to the runtime
adapter, where a real model turn happens. A local diagnostic that posts its own
receipt exists in the operator's repo and is deliberately NOT shipped here.

The construction binds the exact normative source bytes, so a VERIFIED lease
means "this agent is running THIS law", not merely "this session id is known".
h_source/h_payload are derived by importing the framework's own
normative_fragments.build_payload rather than reimplementing it: the broker
derives them the same way and any divergence yields PAYLOAD_BINDING_MISMATCH.
There must be exactly one implementation.

session_identity() prefers the generation FILE over the env var, matching
lease_generation.py. Sending a generation higher than the broker's would revoke
the session's own authority (daemon.py:342-344), so it never guesses.

Verified end-to-end on sb-it-1-dt under a real lease-gated anchor: a mutator
denied rc=2 MUTATOR_UNVERIFIED, then begin -> observe -> promote -> VERIFIED,
then the same mutator allowed rc=0. Negative controls pass: a fresh session is
still denied, and an unrelated session still reads UNVERIFIED — promotion is
per-session and does not leak.

Still open: adapter wiring for step 2. Lazy promotion on first mutator attempt
avoids colliding with the Constitution's first-response mode declaration, since
compare_digest requires the receipt to be the WHOLE message.
2026-08-11 20:51:03 -05:00
Jason Woltje e4dffb7c18 feat(launch): isolate harness homes and record immutable launch provenance
Mosaic wrote into the operator's harness base installs — ~/.claude,
~/.pi/agent, ~/.codex, ~/.config/opencode — for settings, instructions, and a
102-symlink skill farm per harness. Any experiment with hooks or gating
therefore mutated the operator's own tooling, and a broken framework change
could take out the very harness needed to repair it.

Harness home isolation
----------------------
Each runtime now reads config from a dedicated mosaic-owned home via the
harness's own config-dir variable:

  claude    CLAUDE_CONFIG_DIR     ~/.config/mosaic/.claude
  pi        PI_CODING_AGENT_DIR   ~/.config/mosaic/.pi     (replaces ~/.pi/agent)
  codex     CODEX_HOME            ~/.config/mosaic/.codex
  opencode  XDG_CONFIG_HOME       ~/.config/mosaic/.opencode

These paths are manifest-UNKNOWN, so rule 3 (#791) resolves them to operator
ownership and a keep-mode upgrade can neither overwrite nor prune them.
A bare `claude` / `pi` keeps its own config AND auth, making it a structural
break-glass rather than one depending on restoring a file under pressure.

opencode is blunter than the rest: it has no dedicated variable and follows XDG,
so isolation also relocates XDG lookups for anything it spawns. Documented in
place.

mosaic-sync-skills now links into those homes and cleans the legacy farms it
previously planted in base installs. Ownership is proven by RESOLUTION, not by
name — only symlinks resolving inside the canonical/local skills dirs are
removed, mirroring the refusal already in commands/skill.js. Verified against a
real install: codex's own .system directory survived while its 102 mosaic links
were removed. Both resolution prefixes are length-checked first; an empty prefix
would make "$resolved" == "$prefix/"* match every absolute path and delete
foreign symlinks.

Immutable launch record
-----------------------
Every launch now appends one record to fleet/run/sessions/events.ndjson before
exec. Mandatory, mechanical, no model involvement.

pi rewrites its own argv to a bare `pi`, so /proc/<pid>/cmdline destroys the
launch evidence — that has already produced a confident wrong diagnosis ("this
agent bypassed the launcher"), disproved only by the parent's argv and only
because the parent had not yet exited. A record written before exec is the only
place this survives.

The path is the #797 Runtime Session Ledger, already operator-classified and
already covered by test-upgrade-manifest-guard.sh, which seeds it and proves a
populated ledger survives keep-mode upgrades — but nothing shipped ever wrote
it. This implements it in the shape that guard already asserts (0600 files under
a 0700 dir).

`mosaic` writes session.launch; launch-runtime.py appends lease.register with
the broker session id and activation capability. They correlate by an explicit
MOSAIC_LAUNCH_ID, never by pid: execRuntime uses spawnSync, so the runtime is a
child with a different pid.

Records normative fragment digests (CONSTITUTION/AGENTS/SOUL/USER/STANDARDS/
TOOLS/RUNTIME) — the same set the broker hashes for promotion, so drift is
mechanically detectable rather than a matter of judgement.

Credential-safe: env is captured as PRESENT NAMES ONLY, and argv values over
256 bytes become a sha256 + length rather than being inlined.

Also fixes CLI_VERSION resolution: '@mosaicstack/mosaic/package.json' is not in
the package exports map and always throws ERR_PACKAGE_PATH_NOT_EXPORTED.
resolveTool() uses that same failing specifier, which is why its documented
preference for bundled tools over the deployed ~/.config/mosaic copy has never
once applied — noted in place, not fixed here.

Verified on sb-it-1-dt: isolated homes written and base installs byte-identical
for all four harnesses; 408 legacy symlinks removed with 1 foreign entry
preserved; launch records paired across the spawn boundary. typecheck shows zero
errors in launch.ts (the @mosaicstack/types failures are pre-existing and
reproduce on a pristine origin/main worktree).
2026-08-11 20:51:03 -05:00
be-coder-08andJason Woltje f840843908 feat(pr-merge): preserve linked authors in squash messages (#1066)
Co-authored-by: be-coder-08 <[email protected]>
2026-08-11 20:51:03 -05:00
be-coder-08andJason Woltje aacb11b0b9 fix(ci): remove upgrade rollback signal race (#1060)
Co-authored-by: be-coder-08 <[email protected]>
2026-08-11 20:51:03 -05:00
be-coder-08andJason Woltje ce6bda18f2 test(ci): make queue guard harness deterministic (#1062)
Co-authored-by: be-coder-08 <[email protected]>
2026-08-11 20:51:03 -05:00
mos-dt-0 aca28405be Merge pull request 'ci: provision Pi runtime 0.84.1 in the test step (Invariant R)' (#1164) from ci/provision-pi-runtime into next
ci/woodpecker/push/publish Pipeline failed
2026-08-12 01:50:56 +00:00
mos-dt-0 c1eb0659c4 Merge pull request 'docs(framework): adopt MOS-STE writing standard onto next (from #965)' (#1165) from adopt/965-mos-ste-writing-standard into next
ci/woodpecker/push/publish Pipeline failed
2026-08-12 01:18:29 +00:00
Jason WoltjeandClaude Fable 5 b79708fdc7 ci: provision Pi runtime 0.84.1 in the test step (Invariant R)
ci/woodpecker/pr/ci Pipeline was successful
invariant_r_unittest.py (landing with the lease-remediation stack, PR
#1109) hard-requires an installed `pi` binary pinned to the measured
version: it boots Pi's real tool registry and proves the broker's
read-only carve-out resolves to real, unshadowed builtins. Absent
runtime fails loud by design — so CI must provide it.

Install @earendil-works/[email protected].1 (the canonical Pi;
@mariozechner/* is embedded-legacy) at step level in the test step.
Step-level rather than baked into Dockerfile.ci because ci-image
publishes are currently blocked on registry UNAUTHORIZED; baking it in
is the follow-up once registry auth is fixed, at which point this line
degrades to a fast no-op guard like the openssl line above it.

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Dtdjx4Gxude9fwyLezCrhh
2026-08-11 20:16:32 -05:00
jason.woltje ebe415132e Merge pull request 'feat(gateway): generic harness catalog + selection HTTP surfaces (P3 Slice Zero, Task 3)' (#1169) from feat/p3-slice0-task3-catalog-selection into next
ci/woodpecker/push/publish Pipeline was canceled
2026-08-12 01:11:21 +00:00
mos-dt-0 ec260e678f Merge pull request 'fix(git): accept http/https as one scheme class in comment URL verification (#991)' (#1022) from fix/991-comment-url-scheme-normalise into main
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-08-12 01:11:09 +00:00
jason.woltjeandClaude Opus 4.8 f16f206a0a feat(gateway): expose generic harness catalog and selection
ci/woodpecker/pr/ci Pipeline failed
Add the Slice-Zero catalog and selection HTTP surfaces for P3 Task 3:
GET /api/harnesses, GET /api/harnesses/:harnessId/catalog,
GET+PUT /api/chat/preferences/selection. Scope is always server-derived
via scopeFromUser(CurrentUser); selection tuples are validated against the
live catalog with no fallback substitution and persisted in a transitional
owner-scoped in-memory store. HarnessModule is wired into AppModule.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01ESFAnh2t9HmLwng8oW95St
2026-08-11 19:56:11 -05:00
jason.woltje a186922e3a Merge pull request 'feat(gateway): harness registry, fake adapter, no-substitution suite (P3 Slice Zero, Task 2)' (#1168) from feat/p3-slice0-task2-harness-registry into next
ci/woodpecker/push/publish Pipeline failed
2026-08-12 00:40:03 +00:00
jason.woltje 43513c28f7 feat(gateway): add harness registry and fake adapter
ci/woodpecker/pr/ci Pipeline failed
2026-08-11 19:22:27 -05:00
Jason Woltjeandmos-dt-0 b6c12bdfcb style(framework): apply prettier to WRITING-STYLE.md so CI format passes (#965)
ci/woodpecker/pr/ci Pipeline was successful
The `format` step of .woodpecker/ci.yml:89 (`pnpm format:check`) failed on
pipeline 2111 for this branch. Reproduced on a bench with the lockfile-pinned
[email protected] against the repo .prettierrc and .prettierignore, using CI's
exact glob: WRITING-STYLE.md was the only failing file.

The change is mechanical and semantically null: markdown table cell padding
and `*emphasis*` -> `_emphasis_`. Verified by normalizing both revisions
(whitespace removed, `_`/`*` folded, table rules collapsed) — the results are
byte-identical.

This does not address the prose findings published on #965 (P1-P4); those
await a ruling. The `test` step also failed on 2111, on a base ~40 commits
stale — attribution for that failure needs this rerun, and is not claimed here.

Co-authored-by: mos-dt-0 <[email protected]>
2026-08-11 19:00:46 -05:00
Jason Woltje b590a5c3d8 fix(git): accept http/https as one scheme class in comment URL verification (#991)
ci/woodpecker/pr/ci Pipeline was successful
issue-comment.sh and pr-review.sh verify a durable write by pinning the
provider-returned object URL's origin and full path. The origin included the
SCHEME verbatim. On a Gitea whose ROOT_URL is configured `http://` while every
client reaches it over `https://`, the provider returns `http://` object URLs,
so the comparison rejects the provider's own truthful answer about a write that
LANDED. The failure is deterministic, not intermittent: every comment, every
time, on such a deployment.

The scheme was never what the check defends. The forgeries it exists to catch —
look-alike host, decoy path prefix, wrong owner/repo/kind/number — all vary the
HOST or the PATH. Both stay strict. `http` and `https` now collapse to one
scheme class; any other scheme (file:, ftp:, javascript:) stays distinguishing,
and an EXPLICIT non-default port still distinguishes, because a different port
is a different service on the same host.

Consequences of the bug, both observed:

- The wrapper reports failure on a comment that is durably on the issue/PR, and
  attributes it to #865 ("no durable comment created"). The write landed; the
  citation is wrong. Reproduced here: the harness's persisted state contains the
  record while the wrapper exits 1.
- pr-review.sh's comment path is worse. On a host where no seat can create a
  review OBJECT, comment-form is the only gate-16 review record obtainable, and
  this check refuses all of it.

Test gap this closes: every URL fixture in both harnesses was `https://`, and
every negative case varied only host or path. The one axis that fails in
production had zero coverage — the fixtures encoded the assumption that breaks.
Added, in both suites:

- scheme-downgrade (http vs https, otherwise correct) — must be ACCEPTED. Fails
  against the unmodified wrappers, passes against the fixed ones; verified in
  both directions, and the negative control's captured output is the #865
  misattribution above.
- explicit non-default port (`:8443`) — must stay REJECTED.
- non-web scheme (`ftp://`) — must stay REJECTED.

Also fixes test-issue-comment-readback.sh hermeticity (#1007), without which the
suite cannot run on any seat that has a per-agent Gitea token: detect-platform's
step-0 identity lookup reads ~/.config/mosaic/gitea-tokens/<identity>, outside
both XDG_CONFIG_HOME and MOSAIC_CREDENTIALS_FILE, so the suite resolved a
PRODUCTION credential and died at HTTP 401 before case 1. Same two-part fix
already merged for test-pr-review-gitea-comment.sh in #1006: a sandboxed HOME
plus an empty REPO-LOCAL mosaic.gitIdentity to shadow the global. Note the
env-var route does NOT work — detect-platform.sh reads `${MOSAIC_GIT_IDENTITY:-}`
and `:-` treats set-but-empty identically to unset.

The owner-side half of #991 (setting the deployment's Gitea ROOT_URL to https)
is not in scope here and is not made unnecessary by this change; this makes the
wrappers correct against a deployment that returns either scheme.
2026-08-11 19:00:31 -05:00
jason.woltje fb9f9cda5a Merge pull request 'fix(gateway): resolve InteractionCoordinationService handoff factory via optional DI token (#1145)' (#1167) from fix/1145-coord-di-compiled-boot into next
ci/woodpecker/push/publish Pipeline failed
2026-08-11 23:57:43 +00:00
jason.woltje 400a21ca18 Merge pull request 'feat(types): generic harness contracts (P3 Slice Zero, Task 1)' (#1166) from feat/p3-slice0-task1-harness-contracts into next
ci/woodpecker/push/publish Pipeline is pending
2026-08-11 23:51:50 +00:00
shaggy (mosaic-dev box) 4cefa5cd88 fix(gateway): resolve InteractionCoordinationService handoff factory via optional DI token (#1145)
ci/woodpecker/pr/ci Pipeline failed
root cause: emitDecoratorMetadata reflected the third constructor parameter as Function and Nest attempted to resolve it

fix: optional HANDOFF_ID_FACTORY injection token, no production provider, preserving undefined -> crypto.randomUUID() default and unchanged positional construction

TDD: real CoordModule red at Function index [2], then green; test overrides only unrelated AuthGuard because its AUTH provider comes from AppModule's global AuthModule context

Closes #1145
2026-08-11 18:37:54 -05:00
shaggy (mosaic-dev box) ddf8616716 feat(types): add generic harness contracts
ci/woodpecker/pr/ci Pipeline was canceled
2026-08-11 18:32:39 -05:00
30a694358d fix(framework): key §5 lookup on rendered bullets, not the token (mos-dt round-2)
§5 sent the agent to read direct|friendly|formal in USER.md, but the builder
renders prose bullets, not the token — the documented lookup could not key on
the shipped file. Table now keys on the leading bullet USER.md actually
contains. Also: 'concise, technical' -> 'concise, structured' (drop the round-1
residual value name from a rule-9 guide). Docs-only, no code, no scope growth.

Written-by: jarvis (dragon-lin)
Co-Authored-By: Claude Fable 5 <[email protected]>
2026-08-11 18:22:15 -05:00
e01dfa0cd7 fix(framework): ride the existing communicationStyle enum, drop the no-op USER.md edit (mos-dt review #960)
F1: defaults/USER.md is never installed (generated from templates/USER.md.template
via buildCommunicationPrefs). Editing it was a no-op asserting a phantom setting —
exactly the false-green §2 warns against. Reverted.
F2: the framework already has communicationStyle (direct|friendly|formal). §5 now
maps THOSE values to output instead of inventing technical|prose|brief (rule 9).
Minor: §6 states no mechanical prose check exists today; rule 1 points at §3.4.

Written-by: jarvis (dragon-lin)
Co-Authored-By: Claude Fable 5 <[email protected]>
2026-08-11 18:22:15 -05:00
6c4a2eb626 feat(framework): MOS-STE writing standard + Google-style code + per-user comms choice
Adds the agent output standard to the framework SOT so it injects at launch and
is selectable per user (closes the gap: it lived only as a jarvis-brain lab doc + issue #960).

- guides/WRITING-STYLE.md: MOS-STE (adapted ASD-STE100) for docs, Google Style for code,
  verification-artifact emphasis, absolute user-voice carve-out. Written in MOS-STE.
- defaults/STANDARDS.md: Output-standards block (always injected via the prompting contract).
- defaults/AGENTS.md: routing row so writing/doc/comms work reaches the guide.
- defaults/USER.md: per-user 'Comms style' option (technical|prose|brief), default technical.

Refs mosaicstack/stack#960. Owner directive (Jason, 2026-07-30): docs->adapted ASD-STE100,
code->Google style, resumes/personal carved out, comms style a per-user choice.

Written-by: jarvis (dragon-lin)
Co-Authored-By: Claude Fable 5 <[email protected]>
2026-08-11 18:22:15 -05:00
mos-dt-0 540ec5b6ef Merge pull request 'fix(git): #1007 suite hermeticity — pin repo-local mosaic.gitIdentity in five test suites' (#1024) from fix/1007-suite-hermeticity into main
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline failed
2026-08-11 23:19:49 +00:00
mos-dt-0 563d1ac053 Merge pull request 'fix(shell): remove wake validation pipe hazards' (#1107) from fix/1099-pipefail-wake into main
ci/woodpecker/push/publish Pipeline was canceled
ci/woodpecker/push/ci Pipeline was canceled
2026-08-11 23:19:45 +00:00
Mos 4d8ddb9a0a fix: quote SKILL.md descriptions containing colons (silent skill-load failure) (#3) 2026-08-11 22:53:47 +00:00
mos-dt-0 9185b0cce4 Merge pull request 'docs(webui): Phase P structure & migration map' (#1147) from docs/webui-phase-p-structure into next 2026-08-11 22:29:10 +00:00
mos-dt-0andClaude Fable 5 8925a502ae style(webui): prettier-format PHASE-P-STRUCTURE.md
ci/woodpecker/pr/ci Pipeline was successful
format:check was the only red CI step on #1147.

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Dtdjx4Gxude9fwyLezCrhh
2026-08-11 17:14:38 -05:00
mos-dt-0 0e4eb1445c Merge pull request 'fix(installer): propagate wizard gateway failures' (#1134) from fix/wizard-gateway-failure into next
ci/woodpecker/push/publish Pipeline failed
2026-08-11 22:01:43 +00:00
mos-dt-0 592d60425f Merge pull request 'fix(installer): require Node 22 for the --next lane' (#1130) from fix/next-node-gate into next
ci/woodpecker/push/publish Pipeline was canceled
2026-08-11 22:01:39 +00:00
mos-dt-0 a43f343efd Merge pull request 'fix(security): mosaic-init RCE — eval on prompt answers → printf -v (#1115)' (#1127) from fix/mosaic-init-rce into next
ci/woodpecker/push/publish Pipeline was canceled
2026-08-11 22:01:35 +00:00
jason.woltje 88ef9d4fa5 Merge pull request 'P3-R1: repair routing health-enum (#1) + wire /mcp command (#5)' (#1154) from feat/webui-p3r1-routing-mcp into next
ci/woodpecker/push/publish Pipeline failed
2026-08-11 20:51:52 +00:00
shaggy (mosaic-dev box) bda308efd9 fix(gateway): repair routing health and MCP command wiring
ci/woodpecker/pr/ci Pipeline was successful
2026-08-11 15:28:57 -05:00
jason.woltje 20718b5a27 Merge pull request 'P4-1: read-only Projects + Tasks SPA pages + dev-port pins' (#1153) from feat/webui-p4-1 into next
ci/woodpecker/push/publish Pipeline failed
2026-08-11 04:00:36 +00:00
shaggy (mosaic-dev box) 29db24210c fix(web): P4-1 restore graceful degradation for missions/tasks fetch on project detail
ci/woodpecker/pr/ci Pipeline was successful
2026-08-10 22:43:47 -05:00
shaggy (mosaic-dev box)andClaude Haiku 4.5 a6085eea37 feat(web): add read-only project and task SPA pages
Co-Authored-By: Claude Haiku 4.5 <[email protected]>
2026-08-10 22:23:59 -05:00
Mos e00cc475a2 Merge pull request 'P3 — Typed SPA chat (Phase P webUI)' (#1151) from feat/webui-p3-chat into next
ci/woodpecker/push/publish Pipeline failed
2026-08-10 22:57:07 +00:00
mos-dt-0 722163671f feat(pi): add persistent Mosaic /goal controller (#1152)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-08-10 22:54:43 +00:00
shaggy (mosaic-dev box) 7d84e4ee03 fix(gateway): sanitize raw exceptions in /mcp status + /reload sources (P3 re-review#5 blocker)
ci/woodpecker/pr/ci Pipeline was successful
2026-08-10 16:58:07 -05:00
shaggy (mosaic-dev box) 4aaf41dd1a fix(web,gateway): close P3 re-review#4 findings — sanitize all executor catches; lock pre-start turn boundary (wire turnId deferred) 2026-08-10 16:07:12 -05:00
mos-dt-0 bf32f29acd fix(ci): make queue guard purpose-sensitive (#1148)
ci/woodpecker/push/publish Pipeline failed
2026-08-10 20:54:09 +00:00
Jason Woltje 1655b1579a Move deploy and briefs into docs folder. Remove old files.
ci/woodpecker/push/publish Pipeline was canceled
2026-08-10 14:44:19 -05:00
Jason Woltje e478a359eb Move briefs directory inside the docs
ci/woodpecker/push/publish Pipeline was canceled
2026-08-10 14:42:04 -05:00
Jason Woltje 76e4242cb1 Reformat Requirements block
ci/woodpecker/push/publish Pipeline was canceled
2026-08-10 14:40:18 -05:00
shaggy (mosaic-dev box)andClaude Opus 4.8 a45f53071a docs(webui): add Phase P structure & migration map
ci/woodpecker/pr/ci Pipeline failed
First-pass structural reference for the Vite SPA migration (apps/web): dual-app
tree during migration, shared lib/ networking layer, origin-relative/same-origin
serving model, build scripts, the P1-P6 increment map, and the #1145 P5 blocker.
Living doc — details to be fleshed out by follow-up.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01ESFAnh2t9HmLwng8oW95St
2026-08-10 14:34:57 -05:00
Jason Woltje 00eb216480 docs(agents): consolidate project guidance 2026-08-10 14:27:59 -05:00
shaggy (mosaic-dev box) d46a2d675a fix(web,gateway): close P3 re-review#3 findings — sanitize command errors, harden turn-lock & caps 2026-08-10 14:21:52 -05:00
shaggy 8c27024d0e Merge pull request 'fix(gateway): gate FederationModule on tier === 'federated' (#1138)' (#1140) from fix/1138-conditional-federation into next
ci/woodpecker/push/publish Pipeline failed
2026-08-10 07:09:51 +00:00
shaggy (mosaic-dev box) 48bb19310d fix(web): close P3 chat re-review findings 2026-08-10 01:58:27 -05:00
shaggy (mosaic-dev box) 406e40584d test(gateway): raise module-graph import timeout for CI load robustness (#1138)
ci/woodpecker/pr/ci Pipeline was successful
2026-08-10 01:34:24 -05:00
shaggy (mosaic-dev box) 677aeb0c93 fix(gateway): restore daemon config discovery (#1138)
ci/woodpecker/pr/ci Pipeline failed
2026-08-10 00:31:58 -05:00
shaggy (mosaic-dev box)andClaude Haiku 4.5 caebf9ef70 fix(web): harden typed SPA chat lifecycle
Co-Authored-By: Claude Haiku 4.5 <[email protected]>
2026-08-10 00:24:20 -05:00
shaggy (mosaic-dev box)andClaude Haiku 4.5 bd0ef2ab25 fix(gateway): anchor remaining config loads (#1138)
Co-Authored-By: Claude Haiku 4.5 <[email protected]>
2026-08-09 23:54:53 -05:00
shaggy (mosaic-dev box) 2d5a8c81ec fix(gateway): anchor config discovery and isolate env tests (#1138) 2026-08-09 23:11:09 -05:00
shaggy (mosaic-dev box) 884d527cc8 fix(gateway): anchor dotenv discovery to module (#1138) 2026-08-09 22:21:17 -05:00
shaggy (mosaic-dev box) b2e005f2b4 feat(web): add typed SPA chat
Bring the chat experience into the Vite/React-Router SPA on the exact typed
Socket.IO /chat contract from @mosaicstack/types, replacing the /chat
placeholder behind AuthGuard. Surfaces message:ack (with an accessible
status), agent:start, streamed agent:text/agent:thinking, tool start/end
status, agent:end with usage, session:info (thinking controls + routing
decision), commands:manifest, command:result, command:approval (with a
one-time approved-run affordance), system:reload (refreshing the rendered
manifest), and error, and emits message/abort/set:thinking/command:execute/
command:approve with exact payloads.

The gateway does not guarantee message:ack is the first event for a new
conversation (session:info, and error on auth/session-creation failure, can
both arrive first) — conversation-scoped events now adopt the conversation
from whichever scoped event names it first while a send is pending, then
filter everything else against that established conversation. A typed error
stops streaming instead of leaving Stop stuck active; agent:end no longer
appends an empty assistant turn when there is no text or thinking; and a
second message can no longer be sent while a turn is streaming.

Command approval is now integrity-checked end to end: only one
command:approve request may be outstanding at a time (a concurrent request
is ignored rather than overwriting the pending command/args), a stale or
mismatched command:approval response cannot replace active approval state,
and running an approved command clears its approval state immediately (via
a ref, before React re-renders) so a double-click cannot replay
command:execute.

The `/chat` socket is now typed at a single boundary: apps/web/src/lib/
socket.ts narrows socket.io-client's untyped `io()` return value to
`ChatSocket` (Socket<ServerToClientEvents, ClientToServerEvents>) once, at
creation, via the one assertion the library's types force; every consumer
(use-chat-connection.ts) then gets fully checked `on`/`emit` calls with no
further casts. The shared contract types live in the new
apps/web/src/lib/chat-contract.ts (replacing the old spa/chat/types.ts
shim), which re-exports them via type-only imports resolved directly
against packages/types/src (apps/web has no @mosaicstack/types package
dependency, so this stays source-only and is erased at compile time —
no package manifest or lockfile is touched). The two recorded-event test
suites now drive a shared, typed fake socket
(spa/chat/test-support/fake-chat-socket.ts) instead of an untyped
`(event: string, payload: unknown)` harness, so a wrong event name or
malformed payload fails to compile.
2026-08-09 21:39:16 -05:00
shaggy 87daa12976 Merge pull request 'P2 — web SPA data layer + same-origin auth' (#1144) from feat/webui-p2-data-auth into next
ci/woodpecker/push/publish Pipeline failed
2026-08-10 01:52:01 +00:00
shaggy (mosaic-dev box) b82a51da80 fix(gateway): load dotenv before federation tier gate (#1138) 2026-08-09 20:50:37 -05:00
shaggy (mosaic-dev box) 90cf286a09 fix(web): reject protocol-relative auth callbacks
ci/woodpecker/pr/ci Pipeline was successful
2026-08-09 20:43:27 -05:00
shaggy (mosaic-dev box) 0aef432052 docs(scratchpad): record P2 remediation evidence 2026-08-09 20:21:53 -05:00
shaggy 41a16cc916 Merge pull request 'fix(docker): gateway image — git in runner, MOSAIC_ROOT workspace dir, scripts/ in builder, EXPOSE 14242' (#1142) from fix/gateway-runner-image into next
ci/woodpecker/push/publish Pipeline failed
2026-08-10 01:21:30 +00:00
shaggy (mosaic-dev box) e16c08aa9f test(web): align jsdom abort signals with Node 2026-08-09 20:20:30 -05:00
shaggy (mosaic-dev box) a34e92cf39 fix(gateway): harden workspace repository cloning
ci/woodpecker/pr/ci Pipeline was successful
2026-08-09 20:12:39 -05:00
shaggy (mosaic-dev box) a4861c221f docs(scratchpad): record WebUI P2 verification 2026-08-09 20:02:22 -05:00
shaggy (mosaic-dev box) 46d68e1ff4 feat(web): add same-origin SPA authentication 2026-08-09 20:00:22 -05:00
shaggy c3496334a5 Merge pull request 'feat(web): P1 — Vite + React Router skeleton beside Next (Phase P RFC, increment 1/6)' (#1143) from feat/webui-p1-vite-skeleton into next
ci/woodpecker/push/publish Pipeline failed
2026-08-10 00:51:02 +00:00
shaggy 6f29d00149 Merge pull request 'fix: break-C — install-hooks no-ops without git; web image builds @mosaicstack/web' (#1141) from fix/break-c-hooks-and-web-image into next
ci/woodpecker/push/publish Pipeline was canceled
2026-08-10 00:50:19 +00:00
shaggy (mosaic-dev box)andClaude Fable 5 068d0f9b1c feat(web): P1 Vite skeleton beside Next — entry, router, guards, vitest 3
ci/woodpecker/pr/ci Pipeline was successful
First increment of the approved Phase P RFC (webui-mission). Adds a Vite + React
Router SPA scaffold coexisting with the Next app: index.html with the theme
anti-flash script, src/main.tsx entry, the v1 parity route table under Guest/Auth
guard shells, and a dev proxy (/api, /socket.io ws) to the gateway on 14242 so the
SPA is same-origin in dev. vitest bumped to v3 (vite 8 pairing); existing specs
pass unchanged. Next remains the served app until the P5 cutover.

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01ESFAnh2t9HmLwng8oW95St
2026-08-09 19:02:55 -05:00
shaggy (mosaic-dev box)andClaude Fable 5 13cd673d50 fix(docker): gateway runner needs git + MOSAIC_ROOT workspace dir; EXPOSE actual port 14242
ci/woodpecker/pr/ci Pipeline was successful
WorkspaceService shells out to git at runtime and roots workspaces at
$MOSAIC_ROOT/.workspaces — the runner image had no git binary and no
workspace directory. EXPOSE said 4000 but main.ts defaults to 14242.

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01ESFAnh2t9HmLwng8oW95St
2026-08-09 18:03:42 -05:00
shaggy (mosaic-dev box)andClaude Fable 5 620cc608e0 fix(docker): copy scripts/ into web builder — prepare runs install-hooks.mjs on install
ci/woodpecker/pr/ci Pipeline was successful
The layer-cached install copies only manifests and packages/, so the
root prepare script could not be found and pnpm install exited 1
before the git-absent guard could even run.

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01ESFAnh2t9HmLwng8oW95St
2026-08-09 18:03:18 -05:00
shaggy (mosaic-dev box)andClaude Fable 5 91e692e3e7 fix: break-C — install-hooks no-ops without git; web image builds @mosaicstack/web
ci/woodpecker/pr/ci Pipeline was canceled
install-hooks.mjs hard-failed (exit 1) in environments without a git
binary — e.g. the docker image builds, which have no git and no repo.
Hook installation is meaningless there; skip with a warning instead.

docker/web.Dockerfile filtered @mosaic/web, but the package is named
@mosaicstack/web, so the image build compiled nothing.

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01ESFAnh2t9HmLwng8oW95St
2026-08-09 17:58:13 -05:00
shaggy (mosaic-dev box) b4753a75cd fix(gateway): gate FederationModule on tier federated (#1138)
ci/woodpecker/pr/ci Pipeline was successful
CaService hard-requires STEP_CA_URL/provisioner config at construction, so an
unconditional FederationModule import makes every standalone/local boot die at
DI time. Gate the module on loadConfig().tier === federated, matching the
documented intent of the federation compose profile (must not start in
non-federated dev).

Verified in mosaic-dev box: standalone tier boots to "Gateway listening on
port 14242" with bootstrap/socket.io/auth surfaces responding; federated tier
path unchanged.
2026-08-09 17:26:28 -05:00
velmaandmos-dt-0 24bbd40dc7 docs: WebUI fleet Claude bridge — Task 0 decision plan (#1131)
ci/woodpecker/push/publish Pipeline failed
Docs-only plan PR. FRED_APPROVED_REF=0629361ca39a4dd7fb3e575d11c64bea9e545dae (review 147). Merged by fred (orchestrator) via API: pr-merge.sh policy predates the next lane (main-only hardcode) — wrapper fix tracked separately.

Co-authored-by: Velma <[email protected]>
2026-08-09 10:28:41 +00:00
Jason Woltje dc67590a96 fix(installer): propagate wizard gateway failures (#1120)
ci/woodpecker/pr/ci Pipeline was successful
2026-08-09 05:01:09 -05:00
Jason Woltje baf4306f51 fix(installer): require Node 22 for next lane
ci/woodpecker/pr/ci Pipeline was successful
2026-08-09 02:37:03 -05:00
Jason Woltje 12677a928d fix(mosaic): prevent init prompt code execution
ci/woodpecker/pr/ci Pipeline was successful
2026-08-09 00:28:57 -05:00
f10-coder f158be8003 fix(shell): remove wake validation pipe hazards
ci/woodpecker/pr/ci Pipeline was successful
2026-08-07 06:13:47 -05:00
f10-coderandMos b0f7d26dd9 fix(shell): remove test harness pipe hazards (#1106)
ci/woodpecker/push/publish Pipeline failed
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/manual/ci-image Pipeline failed
ci/woodpecker/manual/publish Pipeline failed
ci/woodpecker/manual/ci Pipeline was successful
Co-authored-by: f10-coder <[email protected]>
2026-08-07 11:12:17 +00:00
f10-coderandMos 3a1203b2f8 fix(shell): remove runtime early-exit pipe hazards (#1105)
ci/woodpecker/push/publish Pipeline failed
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: f10-coder <[email protected]>
2026-08-07 09:38:37 +00:00
be-coder-08 df4c591ab4 fix(fleet): make framework shell assertions SIGPIPE-safe (#1100)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-08-07 08:21:20 +00:00
be-coder-06andMos 4fa2768962 fix(fleet): propagate roster git identity (#1073)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: be-coder-06 <[email protected]>
2026-08-07 07:07:45 +00:00
Mos aa0a7b5fa2 fix(tools/git): issue-close.sh silently dropped the closing comment (#1085)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-08-07 05:59:12 +00:00
Mos 42ac19af48 test(gateway): size the enrollment clamp tolerance to CI jitter, not to a fast machine (closes #1090) (#1094)
ci/woodpecker/push/publish Pipeline failed
ci/woodpecker/push/ci Pipeline was successful
2026-08-07 05:33:38 +00: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 85d2108e4e fix(ci): remove upgrade rollback signal race (#1060)
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 22:14:15 +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
mos-dt-0 4df478cdd1 Merge pull request 'chore(sync): merge main → next (B1) — resolve 8 conflicts, restore next current' (#1041) from sync/b1-main-into-next into next
ci/woodpecker/push/publish Pipeline failed
chore(sync): merge main → next (B1) — restore next current, resolve 8 conflicts (#1041)

Brings next current with main incl the RM-03 guard fix (482/5); preserves next's 10 in-flight commits. Closes #1040.
2026-08-03 10:17:06 +00:00
coder-mos2 b8844e1ff0 fix(sync): close local queue semantic merge gap
ci/woodpecker/pr/ci Pipeline was successful
2026-08-02 23:16:09 -05:00
coder-mos2 906ad8dc30 wip(sync): merge main into next with combined resolutions 2026-08-02 23:11:22 -05:00
coder-mos1andmos-dt-0 5916aeefd6 chore(release): @mosaicstack/mosaic 0.0.49 — ship RM-03 guard fix to release channel (#1036)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline failed
Co-authored-by: coder-mos1 <[email protected]>
2026-08-02 20:09:11 +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
coder-mos1andmos-dt-0 f4fd5967fc RM-61: prove ci-postgres teardown discrimination (#1033)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: coder-mos1 <[email protected]>
2026-08-01 14:54:04 +00:00
mos-dt-0andMos f65e9ea656 docs(remediation): mission-state snapshot at the RM-01 seam (#1028)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: mos-dt-0 <[email protected]>
2026-08-01 01:08:11 +00:00
mos-dt-0andMos f58b3699a6 RM-01: reproducible checkout — the pre-push gate fails on code, not environment (#1027)
ci/woodpecker/push/publish Pipeline failed
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: mos-dt-0 <[email protected]>
2026-08-01 00:50:12 +00:00
mos-dt-0andMos 01e966f36d docs(remediation): mission charter + reconciled execution backlog (#1026)
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 22:47:03 +00:00
mos-dt-0andMos 524146055d fix(hygiene): .prettierignore must exclude Python build/test artifacts (#1025)
ci/woodpecker/push/publish Pipeline failed
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: mos-dt-0 <[email protected]>
2026-07-31 22:24:49 +00:00
mos-dt-0andMos 06e0d40352 feat(quality): CI test-membership guard — enumeration can no longer silently under-run the disk (#1017) (#1018)
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 14:08:41 +00:00
Mos 166ee8c90f fix(wake): close fd 9 in the detector's sleep child so a dead detector's lock dies with it (#993)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-31 13:48:33 +00:00
Jason Woltje 2fa6bcd576 fix(git): #1007 — test-issue-comment-readback is a FIFTH affected suite (second census correction)
ci/woodpecker/pr/ci Pipeline was successful
My previous commit said four. It is five. `test-issue-comment-readback.sh` has
the same defect and is fixed the same way, and I had already looked straight at
it and filed it as an *unrelated* silent failure. Correcting that here rather
than folding it in quietly.

WHY IT WAS MISSED — the general lesson, not the excuse. `run_comment()` sends
the wrapper's stdout AND stderr to `$OUTPUT_FILE`, and the `EXIT` trap deletes
`$WORK_DIR`. The suite therefore exits 1 with ZERO bytes on stdout and stderr,
and the one line that says what went wrong —

    Error: Gitea authenticated-identity read failed with HTTP 401

— lives only inside a directory that no longer exists when anyone looks. Every
oracle I had swept the family with greps for a SYMPTOM in surviving output, so
against this suite all of them returned "nothing found", which I read as "clean"
in the first sweep and as "unrelated pre-existing failure" in the second. A
suite that discards or deletes its own evidence converts a post-hoc assay into a
non-measurement, and I wrote that sentence into the previous commit while it was
already false about a file in the same directory.

HOW IT WAS ACTUALLY FOUND. Intercept the identity read at its SOURCE instead of
grepping for its consequence: a PATH shim over `git` that logs every
`mosaic.gitIdentity` read — args, rc, and resolved value — to a file OUTSIDE any
suite's work dir, then execs the real git. Deletion-proof by construction, and
it measures the defect's cause rather than one of its symptoms. Sweeping all 16
suites with it under an ordinary invocation:

  resolves a REAL identity (`mos-dt-0`) before the fix:
    test-issue-comment-readback          1 read   rc=1 (RED on every seat)
    test-pr-review-repo-host-override    6 reads  rc=0
    test-ci-queue-wait-branch-absent     3 reads  rc=0
  the four fixed in the previous commit now read empty; the rest never read at all.

The latter two are NOT affected and are deliberately left alone: under a seat
replica (identity set, no per-slot token) neither reaches `get_gitea_token`'s
fail-loud branch, and under a canary HOME neither carries the canary credential
into any surviving artifact. They read the identity and never enter a credential
path. That residual is structural and belongs to the wrapper half of #1007 —
scoping the read with `git -C "$repo"` removes it for everyone at once.

An earlier version of that sweep reported the four fixed suites as still
resolving a real identity. That was my grep, not the suites: `value=\[..*\]` is
satisfied by `value=[] args=[…]`, because `.*` runs past the empty pair and
matches the closing bracket of the NEXT one. `value=\[[^]]` is the correct test.
Recorded because the wrong pattern failed in the direction that would have sent
me re-fixing four already-correct files.

VERIFICATION of this suite, four HOME arms, all rc=0 with zero non-empty
identity reads and the pass line on stdout: real HOME, seat replica, canary
HOME, and an empty HOME with no identity at all. Full 16-suite sweep after the
change: every suite rc=0.

CONSEQUENCE FOR THE FINDING LIST IN THE PREVIOUS COMMIT: item 2 there — the
"silently red, unrelated to #1007" suite — is withdrawn. It was #1007 all along.
Item 1 (`pr-metadata.sh:89-92`, the anonymous fallback that reports an HTTP 200
carrying valid JSON as "unknown API error") stands and is still unfixed here.

Refs #1007
2026-07-31 07:27:10 -05:00
Jason Woltje 1afe2b36dc fix(git): #1007 suite hermeticity — pin repo-local mosaic.gitIdentity in four test suites
CENSUS CORRECTION: FOUR suites, not the three my own #1007 audit named. The
fourth (test-pr-metadata-gitea.sh) was outside the candidate set that audit
worked from and was found only by sweeping the discriminator across all 16
tools/git/test-*.sh suites. Recording that as a correction to my finding, not
as part of the original claim.

THE DEFECT. get_gitea_token() (detect-platform.sh:502-599) resolves a per-agent
identity at STEP 0, from `git config --get mosaic.gitIdentity`, BEFORE both the
Mosaic credential loader (step 1) and the GITEA_TOKEN env check (step 2). On a
provisioned agent seat that value is set GLOBALLY in ~/.gitconfig and is
inherited by any freshly-`git init`ed repo, so step 0 reads a REAL per-slot
token out of $HOME and returns it without ever consulting the suite's own
MOSAIC_CREDENTIALS_FILE / GITEA_TOKEN fixtures. The suites were running against
production credentials, and the fixture credential each one carefully
constructs was inert.

THE FIX: an empty repo-local `mosaic.gitIdentity`. An empty local value shadows
the global one and reads back empty at rc=0, so step 0 declines. The env route
does NOT work: detect-platform.sh reads "${MOSAIC_GIT_IDENTITY:-}", and `:-`
treats set-but-empty identically to unset.

OPERATIVE vs CONTAINMENT — the two mechanisms are not interchangeable and the
comment in each suite says so. The pin is operative: it prevents the resolution.
The sandboxed HOME each suite now also gets is containment: it bounds a failure
the pin should already have prevented. Conflating them is how this class stays
invisible, because a decoy HOME REMOVES the trigger (~/.gitconfig is where the
global identity lives), so any suite audited under one reads clean however
vulnerable it is. To MEASURE, replicate a seat: a decoy HOME whose .gitconfig
sets mosaic.gitIdentity with no per-slot token, so step 0 reaches its fail-loud
branch. That note is in each file for the next auditor.

SECOND, INDEPENDENT DEFECT in test-pr-metadata-gitea.sh. Applying the pin alone
turned that suite RED — and a control at baseline 826a8b3 under a plain HOME
reproduced the same failure, so it is pre-existing, not introduced. Its
`GITEA_TOKEN="stub-token"` / `GITEA_URL="https://git.example.test"` pair can
never satisfy step 2, because step 2 accepts GITEA_TOKEN only when GITEA_URL
matches the remote host and this repo's origin is git.uscllc.com. The suite had
therefore only ever passed by resolving a REAL credential — step 0 on a seat, or
step 1 from the operator's own credentials.json. A MOSAIC_CREDENTIALS_FILE
fixture is added rather than leaning on the sandboxed HOME making step 1 find
nothing: a test that passes because production configuration is ABSENT fails the
moment it is present. Shipping the pin without this would have moved the failure
rather than removed it.

NO CI ARM. .woodpecker/ci.yml does not run these suites; packages/mosaic/
package.json:28 (test:framework-shell) runs an ENUMERATED list that excludes all
four. They run only by hand — i.e. exclusively on a provisioned seat, the one
environment where the defect is live. "Passes in CI, fails on a seat" does not
apply here; there is no CI observation at all.

VERIFICATION (seat replica = decoy HOME with mosaic.gitIdentity set, no per-slot
token; canary = same plus a marked non-credential at both per-slot paths; plain
= empty HOME; real = ordinary invocation):
  - bash -n clean on all four.
  - Sweep of all 16 suites at baseline 826a8b3 under the seat replica:
    test-gitea-login-resolution rc=1 REACHES-STEP0; test-issue-create-
    interactive-auth rc=1 REACHES-STEP0; test-pr-merge-gitea-empty-uid rc=1
    REACHES-STEP0; test-pr-metadata-gitea rc=1 REACHES-STEP0.
  - Same sweep after: every row rc=0 with step0 absent.
  - test-gitea-token-identity flags REACHES-STEP0 in BOTH arms and is NOT a
    defect: it runs under `env -i HOME="$FAKE_HOME"` (line 77) and its hit is
    its own deliberate assert_failloud fixtures (lines 158-171). The fail-loud
    grep matches the intended behaviour as well as the defect, so it needs the
    second discriminator; recorded here so the next sweep does not re-file it.
  - Durable-argv assay (a PATH shim that tees argv out of each suite's own mock
    curl, because test-pr-merge-gitea-empty-uid truncates its log between phases
    and its EXIT trap removes the sandbox — a post-hoc read of that suite is a
    non-measurement, and "no trace" there is not a clearance):
      test-pr-merge-gitea-empty-uid  before: canary token in argv, fixture never
        used. after: fixture token in argv, canary absent. 5 curl calls both arms.
      test-pr-metadata-gitea         before: canary in argv. after: both calls
        carry the fixture token against git.uscllc.com.
  - test-pr-metadata-gitea across seat/canary/plain HOMEs after the fix: rc=0,
    rc=0, rc=0.
  - All four under the real HOME: rc=0. No regression to ordinary invocation.

The comment block is duplicated across the four files rather than pointing at a
shared note. Deliberate, and matching the merged #1006 precedent
(test-pr-review-gitea-comment.sh:87-95): the reader who needs it is auditing one
file.

TWO FINDINGS DELIBERATELY NOT FIXED HERE (out of this branch's scope, to be
filed):
  1. pr-metadata.sh:89-92 — the anonymous curl fallback does not check ^2, so an
     HTTP 200 carrying valid JSON is reported as "unknown API error" at rc=1.
  2. test-issue-comment-readback.sh exits 1 with ZERO bytes on stdout AND
     stderr, dying at its first seed_state python3 heredoc. Reproduces at
     baseline 826a8b3 under both a seat replica and the real HOME. Silently red
     at main for everyone; unrelated to #1007.

Refs #1007
2026-07-31 07:13:13 -05: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-dt-0andMos a4280b9c98 fix(wake): #984 fatal source guard + #985 absorb re-scan — #973 follow-up batch (#1001)
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:16:22 +00:00
Mos 4fb44f6345 fix(wake): three-valued grep verdicts — has_match/count_lines across all ten suites (closes #973) (#983)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-31 08:39:04 +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
mos-dt-0andMos 76eef39a29 docs(wake): #953 dead-letter retention recorded as load-bearing at the write site (#968)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
Closes #953.

GATE RECORD: review CLEAR at this exact head (author != reviewer, pre-registered diff-blind checks) + terminal-green CI at this exact head + queue guard clear.
CI CAVEAT (#973): green on the wake suites is currently WEAKER THAN IT LOOKS, IN BOTH DIRECTIONS. grep error/spawn exit codes are read as absence across 257 assertion sites in six idiom forms; 36 inverted (&&-fail) sites — including 19 credential-security canaries — fail toward GREEN under load. These greens were obtained on solo reruns after load-correlated FALSE reds (2115/2116/2118; main itself was red). This merge's safety therefore rests on the CONTENT review, not on the green. Remediation charter fa551c2d0 is authored and in flight.

Co-authored-by: mos-dt-0 <[email protected]>
2026-07-30 23:25:38 +00:00
mos-dt-0andMos 47f8689231 fix(wake): #952 quarantine-audit clean sweep names BOTH unprovable residual classes (#967)
ci/woodpecker/push/publish Pipeline was canceled
ci/woodpecker/push/ci Pipeline was canceled
Closes #952.

GATE RECORD: review CLEAR at this exact head (author != reviewer, pre-registered diff-blind checks) + terminal-green CI at this exact head + queue guard clear.
CI CAVEAT (#973): green on the wake suites is currently WEAKER THAN IT LOOKS, IN BOTH DIRECTIONS. grep error/spawn exit codes are read as absence across 257 assertion sites in six idiom forms; 36 inverted (&&-fail) sites — including 19 credential-security canaries — fail toward GREEN under load. These greens were obtained on solo reruns after load-correlated FALSE reds (2115/2116/2118; main itself was red). This merge's safety therefore rests on the CONTENT review, not on the green. Remediation charter fa551c2d0 is authored and in flight.

Co-authored-by: mos-dt-0 <[email protected]>
2026-07-30 23:25:34 +00:00
mos-dt-0andMos 8d1d6e5e76 feat(wake): #958 A11 preimage.sh — durable provenance for the operator-side preimage definition (#964)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
Closes #958.

The preimage definition (source-adapter.sh) is the single most consequential file in the wake pipeline — every observed_hash is a sha256 of what it emits — and it was UNVERSIONED: no git history, no backup. When it was edited at 07:27 on 2026-07-30, attribution was recoverable only because an agent transcript happened to still be on disk. A11 gives that file durable provenance (option (2) of #958: recorded content-addressed, not in-band).

DESIGN, per the pre-registration:
- Provenance is OUT-OF-BAND (never on the adapter's stdout) — an in-band record would advance observed_hash for every source at once and manufacture the re-baseline it exists to explain (B3).
- The obligation never depends on the provenance path: a missing/corrupt store cannot halt the detector or swallow a wake (#940 advisory-fields precedent; B4).
- DESC_FMT=d1 is NOT the provenance record — the tag versions the descriptor FORMAT; a behaviour change that keeps descriptor shape re-baselines every hash and leaves the tag unchanged (B6).

CREDENTIAL HARD GATE (rebuilt after the first verdict FAILED it): byte capture is now RECORD-ONLY BY DEFAULT (extras opt in via WAKE_PREIMAGE_CAPTURE), not allow-by-default-refuse-on-shape — because a shape list can only refuse the secrets someone already enumerated, and the tool's own usage text recommended adding detector.env (where HMAC material lives). Deny is evaluated on BOTH raw and resolved path forms with resolved anchors, ordered before allow — closing the realpath-before-deny ordering defect that let a renamed symlink target through.

VERIFICATION (reviewer, mos-dt, independent of the author's claims):
- Seven decoy cases by planted-marker-then-grep-whole-state-dir: known cred path / same-name symlink / RENAMED-target symlink / prefixed secret / prefixless secret / opted-in-symlink-to-DENIED-target all REFUSED; opted-in-symlink-to-ALLOWED-target CAPTURED (positive control that the harness can capture at all, and that C was not closed by breaking every symlink).
- Polarity-completeness self-test RE-RUN with the shape list stubbed always-allow AND both deny lists stubbed — case D still safe: the flip is complete, the shape list is not load-bearing. Each stub proven live first (a stub that silently fails to apply reports the dangerous state as safe).
- B11: rm-then-change fails LOUD (rc=1), refuses to re-baseline, leaves the ledger absent; absent-with-emptied-objects still first-installs cleanly (absent-is-not-corrupt not paid for by breaking first install).
- RED-first reproduced exactly P13-P16 pre-fix; each refusal corroborated three ways (loud stderr, ledger row captured:false WITH a hash so attribution survives refusal, objects/ holding only the adapter).

KNOWN RESIDUAL (filed #969, non-gating): the deny check is both-forms but the suite needles only the resolved form — a deny reduced to resolved-only survives 17/17 green and would leak a renamed-symlink case. No reachable leak at this head (shipped code correct on all seven decoys); it constrains a FUTURE edit. Doctrine: a both-forms fix needs a needle per form; a fixture that satisfies its assertion through a DIFFERENT rule is testing the rule it did not mean to test.

Authored by pepper (sb-it-1-dt); independently reviewed by mos-dt (sb-it-1-dt) under diff-blind pre-registration (7242688b1, predating first read) — NOT CLEAR on the first verdict (B2/B11 failed by decoy), CLEAR at 8aff7d8 after the polarity rebuild. Manifest version 0.7.0.

Co-authored-by: mos-dt-0 <[email protected]>
2026-07-30 21:48:06 +00:00
mos-dt-0andMos 6a7fce34bb fix(wake): #946 digest ack watermark clamped at quarantined seqs — disclose AND clamp (#951)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
Closes #946.

The digest omitted a quarantined entry's claim from disclosure while still advancing the ack watermark it instructed the consumer to run — converting a fail-safe HOLD into a silent DISCARD, through the documented normal path. Measured: the burial instruction was re-issued FIVE times, four fresh digests plus one system-initiated redelivery fired purely because the entry had gone unconsumed for 1826s. That redelivery is the proof of the 'indefinitely' half: the mechanism re-asserted itself with no new information.

SCOPE — this was NOT a missing check in the consume path. Measured before the fix: dead-letter occurrences were digest.sh 27, store.sh 0, ack.sh 0, detector.sh 0, reconcile.sh 0. Quarantine was owned ENTIRELY by the renderer; the store that advances the watermark had zero knowledge the ledger existed, so an entry could be quarantined by one subsystem and consumed by another with no possible interaction. The fix is therefore a deliberate cross-module decision — option (b), quarantine recorded into a store-owned file, preserving the existing direction of dependency — pre-registered by the consumer before any diff existed.

VERIFICATION
- Pipeline 2107 terminal SUCCESS at e11bc6622, read clone-inclusive from the provider API rather than through `pipeline-status.sh` (which filters `.type != "clone"` per workflow and would hide a clone failure behind an all-green table): 9/9 children success, exit 0 each, no non-success member. Its `test` step runs all nine wake harnesses via turbo -> packages/mosaic `test` -> `test:framework-shell`.
- Independent review by the consumer on the affected lane: eleven pre-registered acceptance checks, authored and delivered BEFORE the diff was read — the file list deliberately unlooked-at, because a filename alone would have disclosed which option was chosen. All eleven resolved, no blocker.
- The check that decides it: a RAW `ack.sh consumed --upto N` with no digest involved must refuse to advance past a quarantined seq — the case an agent hits when a digest is MISSED, and the one that would have sunk a disclosure-only fix. Covered at the head as a named assertion (T13 ordinary-path bypass), written independently of the reviewer's list.
- Mutation: one asserted site disabled -> TWELVE assertions die, every one BEHAVIOURAL, ZERO count assertions, including one killing across the module boundary the fix spans.
- RED control at base a6b5f6a: 34 and 10 assertions fail, matching the body exactly.
- Coordinator re-verify by a different instrument than the reviewer used: static reference counts across the base/head boundary — store.sh 0 -> 49, ack.sh 0 -> 6, `--agent` unchanged at 4 (so #949 correctly stayed out). A fix present-but-inert passes the count and fails the mutation; a fix behaviourally correct but smuggling #949 passes the mutation and fails the count. Neither result is reachable by repeating the other.

KNOWN RESIDUALS
- The `consumed-hashes` repair criterion is met only for keys that RE-EMIT. A corrupted row whose key never recurs stays false indefinitely; the sweep covers those, and the known-false row named in the acceptance criteria had already self-healed by re-emission rather than by design — safe by population, not by design.
- The audit's clean-sweep message names one unprovable class; a second exists (a surviving dead-letter row with an empty `observed_hash` cannot be convicted either). Wording, not logic. Filed separately.
- The audit's provability bound makes dead-letter RETENTION load-bearing for auditability. Nothing prunes it today, so this is latent — but any future rotation or size cap silently converts provable rows into unprovable ones with no signal at either end. This is not a defect; it is a property that BECAME load-bearing and is recorded nowhere. Filed separately.
- `test-wake-detector.sh` D4 fails at this head AND identically at base, with an empty diff over detector files — pre-existing, tracked, not introduced here.

Authored by pepper (sb-it-1-dt); reviewed independently by mos-dt (sb-it-1-dt). The mos-dt-0 commit and fork identity does not identify the author — attribution collapse tracked separately.

Co-authored-by: mos-dt-0 <[email protected]>
2026-07-30 15:41:03 +00:00
mos-dt-0andMos a6b5f6a01a fix(wake): #944 path becomes a hard-locator arm — detector-shape actionable entries pass the §2.1 gate (#945)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
Closes #944.

_has_hard_locator accepted only repo+issue / 40-hex sha / file — the forge vocabulary. The detector emits path (+snapshot_sha when attested) and NEVER emits file/issue/sha, so predicate and sole producer shared ZERO keys and every class=actionable board_file entry dead-lettered. Latent since #920, whose harness pinned the detector's own emission shape as its malformed example — the suite certified the gap it was written to guard.

Fix: `path` becomes a hard-locator arm, and ONLY path. Bare path-less snapshot_sha is a deliberate NON-arm (would widen past the board_file vocabulary); Q11(d) asserts it still quarantines at 7/40/64 chars, spanning the detector's ^[0-9a-f]{7,64}$ attestation range.

VERIFICATION
- Pipeline 2105 terminal-green at fa36da8. Its `test` step reaches all nine wake harnesses via turbo -> packages/mosaic `test` -> `test:framework-shell`, which names each suite explicitly. The two-levels-down indirection matters: no search of .woodpecker/* can see it, and that is exactly why this question was got wrong earlier today and then corrected. CI therefore DOES attest the quarantine suite and the detector suite at this head.
- Independent review (mos-dt, consumer on the affected lane) PASS at fa36da8, from a detached worktree: predicate provably unmoved from fb3c3c3 (comment-stripped sha256 identical, _has_hard_locator body byte-identical), RED control at base reproduced exactly 8 failures all Q11 including "got 6".
- Third reviewer (wake-judge) ACCEPT on both judgment calls: the Q1 assertion reversal is a legitimate correction (the flip was forced, not elective — base fixtures red 19 assertions against the head predicate) and path-alone satisfies §2.1, whose operative test is "one targeted call, never a search" — two of its four named exemplars already resolve to current state. Requiring path+snapshot_sha jointly would permanently dead-letter a declared source class and conflict with #940's advisory-fields ruling.
- Judge's mutation criterion met: with the reconciled exemption disabled, the gate-level assertion ("an ORIENTATION-tier enumeration must NOT be quarantined") dies at this head and did not exist as a casualty before F1.
- D4 (detector lock re-acquisition) fails intermittently at base AND head; git diff base..head over the detector files is EMPTY, so it is out of this PR's surface on structural grounds rather than on a re-roll. Known defect, fix identified (detector.sh:516, fd 9 leaked into sleep), tracked separately.

KNOWN RESIDUALS
- ENUM-B is now the sole address-free reconciled fixture, so the exemption's gate-level guard is a population of one. Safe by population, not by design. Author follow-up: assert ENUM-B carries no hard-locator arm so the harness guards its own premise.
- The binding spec (CONVERGED-DESIGN.md §2.1, separate repo) still enumerates four forge tokens and reads narrower than the shipped gate. Tracked as #948, sequenced after the dragon-lin reseed.
- Hard-locator arms are type-loose: repo/file/path accept any non-null JSON value. Pre-existing; `sha` fails closed only by accident of test(). Tracked separately.

Authored by pepper (sb-it-1-dt); reviewed independently by mos-dt (sb-it-1-dt) and wake-judge. The mos-dt-0 commit/fork identity does not identify the author — attribution collapse tracked in #3092.

Co-authored-by: mos-dt-0 <[email protected]>
2026-07-30 14:01:48 +00:00
mos-dt-0andMos 539b475a92 fix(wake): #943 whole-string validation for WAKE_SNAPSHOT_TS_FUTURE_SLACK + version 0.6.13
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
grep is line-oriented, so a multi-line knob value passed the per-line anchors and was still fatal in arithmetic. Replaced with a case pattern matching the whole string, so an embedded or leading newline rejects. Manifest bumped 0.6.12 -> 0.6.13: three materially different detectors had shipped under one version string, and version= is the component sole self-identity claim.

Authored-by: pepper
Reviewed-by: mos-dt (independent, at this head; transfer proven by blob-hash equality)
Merged-by: Mos
Co-authored-by: mos-dt-0 <[email protected]>
2026-07-30 11:56:18 +00:00
mos-dt-0andMos 3e47fc076f fix(wake): #942 harden WAKE_SNAPSHOT_TS_FUTURE_SLACK — validate shape AND force base-10
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
The slack knob was interpolated raw into $((...)) under set -u: a malformed value was FATAL to the poll, falsifying the poll-never-fails invariant, and a negative value inverted the guard to deny-all. Shape validation alone was insufficient — bash reads a leading zero as octal, so 08/09 passed the regex yet were fatal and 0300 silently meant 192. Now validated ^[0-9]{1,9}$ with a loud fallback to 300, then forced to base-10 via 10# so the knob means what the operator wrote.

Authored-by: pepper
Reviewed-by: mos-dt (independent, found both the original defect and the radix residual)
Merged-by: Mos
Co-authored-by: mos-dt-0 <[email protected]>
2026-07-30 11:17:51 +00:00
mos-dt-0andMos 8710d0f6d7 feat(wake): #940 snapshot-datable digests — fd-3 snapshot-metadata channel (#941)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
Adapter emits snapshot sha/ts out-of-band on fd 3 so a changing value never enters the delta-gate hash. Detector validates advisorily (sha regex, epoch sanity before arithmetic, future-skew slack); malformed metadata is dropped loudly and never gates the wake. Digest renders snapshot_sha/snapshot_ts plus a git-show re-verify hint. Adapters that never write fd 3 are byte-identical.

Reviewed-by: Mos (design, independent)
Reviewed-by: mos-dt (artifact, hardening §2)
Co-authored-by: mos-dt-0 <[email protected]>
2026-07-30 10:55:18 +00:00
jason.woltjeandMos b981b4ec10 fix(wake): #934 mount-free, privilege-invariant seq-integrity fault injection (T9/T11 run in non-priv CI) (#936)
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-26 16:34:58 +00:00
jason.woltjeandMos 9e81ffd7fc fix(wake): #932 stop reconciler re-enumerating already-CONSUMED detector state (#935)
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-26 15:48:40 +00:00
jason.woltjeandMos 9becaf877f fix(wake): #917 gate the final observed_seq cursor write + observed.set/cursor consistency (defense-in-depth) (#933)
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-26 15:14:38 +00:00
jason.woltjeandMos 17087efe15 fix(wake): #925 framework-ship canon fallback-wake (systemd timer + schema bound + A10 install/validate) — F7 out of the box (#931)
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-26 13:44:51 +00:00
jason.woltjeandMos 0ea41e848b fix(wake): #913 installer adoption gaps — _lib dep-check fail-loud + mosaic-wake.service systemd-search-path link+validate (#930)
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-26 12:37:29 +00:00
jason.woltjeandMos 347c1d57c1 fix(wake): #924 route dead-letter quarantine alarm via WAKE_ALARM_SINK_CMD with per-observed_seq dedup (G2a) (#929)
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-26 11:45:09 +00:00
jason.woltjeandMos 13e6ce5e5c fix(wake): #927 enqueue TOCTOU — move stale-tmp cleanup off the hot enqueue path (no concurrent in-flight-write clobber) (#928)
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-26 10:56:40 +00:00
jason.woltjeandMos 90265ef550 test(wake): #923 de-flake T10 concurrent-enqueue race (deterministic barrier) (#926)
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-26 10:23:07 +00:00
jason.woltjeandMos 937a276208 fix(wake): #920 quarantine render-refused drain entry (no head-of-line block) + reconciler enumerations render orientation-tier (reconciled:true, render-tier not class=digest) (#922)
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-26 08:45:51 +00:00
jason.woltjeandMos 712c770b7a fix(wake): #912 exercise the digest/HMAC trust suite in real CI (fix runner divergence + openssl + hard-require) (#921)
ci/woodpecker/push/ci-image Pipeline was successful
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-07-26 08:11:28 +00:00
jason.woltjeandMos d967a4a926 fix(wake): #914 digest renderer — WAKE_AGENT-prefixed ack line + digest-class locator threading (#916)
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-26 07:13:07 +00:00
jason.woltjeandMos c585ac3326 test(wake): #918 de-flake T7 ack-no-network-block (sub-second timing) (#919)
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-26 06:46:28 +00:00
jason.woltjeandMos e2ec927b1c fix(wake): #908 unify observed_seq on a single store-side allocator (dissolve detector-private-counter seam) (#915)
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-26 06:02:02 +00:00
jason.woltjeandMos 2378665eaf feat(wake): W7 A10 idempotent installer + mosaic-wake.service (component-manifest, Gate-A, blank-reset retire, snapshot-guard, fail-closed install-validate) (#911)
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-26 04:19:09 +00:00
jason.woltjeandMos 003cdaa1a6 feat(wake): W6 — off-host dead-man beacon + pluggable alarm-sink adapter (#910)
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-26 02:30:28 +00:00
jason.woltjeandMos 320f5bfb6f feat(wake): W5 — synthetic-canary FN-oracle + source-parity reconciler (#909)
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-26 02:04:19 +00:00
jason.woltjeandMos 5df47e735e feat(wake): W4 — per-host delta-gated detector daemon (fail-loud source semantics, enqueues to W2 store) (#907)
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-26 01:04:55 +00:00
jason.woltjeandMos dd1391fd76 fix(wake): digest hard-locator gate covers top-level .claim entries (Closes #905) (#906)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was canceled
Co-authored-by: jason.woltje <[email protected]>
Co-committed-by: jason.woltje <[email protected]>
2026-07-26 00:58:40 +00:00
jason.woltjeandMos 10d957d095 feat(wake): W3 — cumulative-state digest renderer + non-circular HMAC signer (#904)
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-26 00:32:12 +00:00
jason.woltjeandMos dc45eb7c30 feat(kbn): land KBN-101 Envelope A v6 (rc.20) — declarative sink-RBAC + RLS write-source (Form A) (#902)
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 23:58:18 +00:00
jason.woltjeandMos 28f022d9c0 feat(wake): W2 — three-cursor durable store + RECEIVED/CONSUMED ack-wrapper + watch-list schema (#903)
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 23:58:08 +00:00
jason.woltjeandMos 2726fab5e0 chore(framework): wire agent-send.test.sh into CI test:framework-shell (W1 follow-up) (#901)
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 23:23:24 +00:00
jason.woltjeandMos ab6e8e80dc fix(framework): send-message.sh fail-loud submission verdict + regression tests (Patch 6) (#895)
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 22:57:11 +00:00
jason.woltjeandMos 1933c6cb1d feat(framework): accept digest message class in agent-send.sh (W1) (#894)
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:56:46 +00:00
jason.woltjeandMos 48a0c86093 fix(lease-broker): recovery_runtime_unittest wait_ready() connect-probe (co-equal CI flake, cherry-pick #898) (#900)
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 22:26:38 +00:00
jason.woltjeandMos 79c8647fd9 fix(lease-broker): wait_ready() polls real connect-readiness not socket-file existence (flaky CI race) (#898)
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 22:10:15 +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 4c117afe03 docs(framework): add WAKE-DOCTRINE.md guide (W0) (#893)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was canceled
Co-authored-by: jason.woltje <[email protected]>
Co-committed-by: jason.woltje <[email protected]>
2026-07-25 21:57:51 +00:00
jason.woltjeandMos 2698ddb7b5 feat(comms): P1 presence — minimal Synapse + fleet presence room + mosaic.presence heartbeat + liveness (#888)
ci/woodpecker/push/ci-image Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
Co-authored-by: jason.woltje <[email protected]>
Co-committed-by: jason.woltje <[email protected]>
2026-07-25 21:03:18 +00:00
jason.woltjeandMos fabde1c834 docs(rfc): add RFC-001 (MACP/Matrix-native comms) + RFC-002 (install/config/topology) (#886)
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 21:02:54 +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 529c177830 fix(update): mosaic update runs the install-ordering guard post-reseed (#882 --sync-only bypass) (#883)
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-23 22:18:34 +00:00
jason.woltjeandMos a32ce4c8f9 feat(869-c4): activation version-coupling assertion (Part of #869)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
Part of #869

Mos (id-11) Gate-16 merge: independent APPROVE @90eb48fa (fail-closed identity locks byte-unchanged verified), author id2 != approver id11, clean mosaic-coder author, CI green wp1992. #869 Point-1 CODE COMPLETE (C1/C3/C5/C2/C4).

Co-authored-by: jason.woltje <[email protected]>
Co-committed-by: jason.woltje <[email protected]>
2026-07-23 19:07:27 +00:00
jason.woltjeandMos d351caad36 feat(869-c2): install-ordering enforcement-hook guard (Part of #869)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
Part of #869

Mos (id-11) Gate-16 merge: independent APPROVE @b6f36564 (8/8, verified vs real production settings template), author id2 != approver id11, clean mosaic-coder author, CI green wp1988.

Co-authored-by: jason.woltje <[email protected]>
Co-committed-by: jason.woltje <[email protected]>
2026-07-23 18:48:33 +00:00
jason.woltjeandMos 76b86a246e feat(869-c5): mosaic doctor activation-check (Part of #869)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was canceled
Part of #869

Mos (id-11) Gate-16 merge: independent APPROVE @e75e3238 (8/8), author id2 != approver id11, clean mosaic-coder author, CI green wp1987.

Co-authored-by: jason.woltje <[email protected]>
Co-committed-by: jason.woltje <[email protected]>
2026-07-23 18:38:21 +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 2f50c0876b feat(869-c3): lease-broker supervisor unit (Part of #869)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was canceled
Part of #869

Mos (id-11) Gate-16 merge: independent APPROVE @75235ef8 (9/9, no live host mutation), author id2 != approver id11, CI green wp1971.

Co-authored-by: jason.woltje <[email protected]>
Co-committed-by: jason.woltje <[email protected]>
2026-07-23 17:19:48 +00:00
jason.woltjeandMos db90da347e feat(869-c1): activation-capability probe (Part of #869)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was canceled
Part of #869

Mos (id-11) Gate-16 merge: independent 3-round APPROVE @c5a2bcc5, author id2 != approver id11, CI green wp1973.

Co-authored-by: jason.woltje <[email protected]>
Co-committed-by: jason.woltje <[email protected]>
2026-07-23 17:14:57 +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 b79336a8c1 feat(orchestrator): board-roll.sh — auto-roll LIVE board to LEDGER under byte cap (#868)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline failed
feat(orchestrator): board-roll.sh - auto-roll LIVE board to LEDGER under byte cap

Closes #868
2026-07-22 09:20:03 +00:00
jason.woltje 4e5af23214 Merge pull request 'skills: add glpi-* family (solve, followup, sweep, list, create)' (#863) from feat/glpi-skills into main
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-21 01:09:50 +00:00
Hermes Agent 880c28b191 docs(glpi-skills): genericize operator-specific content per review
ci/woodpecker/pr/ci Pipeline was successful
2026-07-20 19:45:50 -05:00
Jason WoltjeandClaude Opus 4.8 7bc2dfb6c8 skills: add glpi-* family (solve, followup, sweep, list, create)
ci/woodpecker/pr/ci Pipeline was successful
GLPI helpdesk workflow skills written against the portable
tools/glpi/ tooling (session-init.sh, ticket-list.sh, ticket-create.sh),
cross-linked via [[glpi-*]]:

- glpi-solve    — close a ticket by setting status Solved (5); GLPI auto-closes
- glpi-followup — add a followup via the top-level /ITILFollowup endpoint
- glpi-sweep    — read-only hunt for done-but-open tickets needing Solve
- glpi-list     — query tickets by status/recency
- glpi-create   — open a new ticket

Core rule encoded: completing work means setting status Solved, not just
posting a resolution followup (a followup documents; only Solved auto-closes).

Note: illustrative examples in the bodies are USC-flavored (M2M / helpdesk
ticket numbers) and can be genericized in review if preferred.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_019GjBgrb9tHgvq414Fqj37c
2026-07-20 18:04:53 -05:00
jason.woltje b0d78d8632 fix(mosaic): de-flake mutator-class lease gate TTL-expiry test (#861)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-20 10:32:45 +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 acd7d380f6 fix(framework): install deps on worktree bootstrap + legible deps-preflight at gate seam (#856) (#858)
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/push/publish Pipeline was successful
2026-07-20 09:38:12 +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 11d2818453 docs(tasks): FCM-M5-001 done — verified completion evidence (supersedes #848) (#853)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-20 07:45:08 +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 77c9a82614 fix(lease-broker): de-flake recovery_runtime b2 broker-socket ConnectionRefused race (#849) (#851)
ci/woodpecker/push/publish Pipeline was canceled
ci/woodpecker/push/ci Pipeline was canceled
2026-07-20 06:44:37 +00:00
jason.woltje 627cf2bb38 docs(fleet): add operator configuration guide (#789)
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/push/publish Pipeline was successful
2026-07-20 05:22:25 +00:00
jason.woltje 0582a8912b WI-7 #834: T-C server-side branch-protection posture + R1 honesty amendment (#847)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-20 04:20:02 +00:00
jason.woltje 2509eb7646 WI-6 (#833): constrained recovery command + mosaic-context-refresh skill wrapper (#846)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-20 03:33:00 +00:00
jason.woltje 07553ead33 WI-5 #832: Receipt-challenge protocol (compaction-refresh, milestone 188) (#845)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-19 23:18:56 +00:00
jason.woltje e522b22fa4 WI-4 (#831): verbatim-hashed normative fragments (B_payload/H_payload) (#844)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-19 20:34:20 +00:00
jason.woltje e4d7d4502d WI-3 (#830): compaction observers → revoke + D4 same-PID generation auto-revoke (#842)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-19 19:46:28 +00:00
jason.woltje 8dfcf1903e fix(#838): bound broker reply deadlines + fail-close empty-read; de-flake acceptance harness (#839)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
Bound broker reply deadlines (separate read/lock/send budgets, BROKER_BUSY-before-mutation, fresh post-handle send budget → closes drop-after-commit window); fail-close empty/truncated read → GATE_UNAVAILABLE deny. De-flakes the 1917 acceptance surface. terra CODE APPROVE (pi) + Opus SECREV APPROVED (claude) — RoR comment 18143. Promote-lease-lost-ACK residual = fail-safe two-generals observability-gap, routed to WI-3 D2-v5 as named-disclosed-bounded-residual (route i). Gate-16 3-principal author=gpt-sol.

closes #838
2026-07-18 07:15:50 +00:00
jason.woltje abd2791f59 feat(mosaic): WI-2 mutator-class guard for directive-freshness (#837)
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/push/publish Pipeline was successful
WI-2: mutator-class guard for the compaction directive-freshness mechanism — command-position parser (prefix x var-indirection unified) + primitive-anchored invariant backstop + all-tools-hook fail-close. Parser-complete on principle: realistic evasion matrix RED-regression-covered, residual exotic evasions proven backstop-caught (B-tests), lens-convergence reached.

closes #829
2026-07-18 05:51:58 +00:00
jason.woltje 8ec67a1126 feat(mosaic): add authenticated external lease broker (#836)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-18 03:12:23 +00:00
jason.woltje d801d6c4c8 feat(mosaic): add secure skill registration CLI (#826)
ci/woodpecker/push/ci-image Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-07-17 23:45:35 +00:00
jason.woltje d3bf52898b fix: reject unknown installer arguments (#825)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-07-17 22:16:51 +00:00
jason.woltje 3f77229e88 fix(#792): fleet roster ENOENT actionable exit + installer heading printf (#818)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-07-17 21:36:36 +00:00
jason.woltje 686c881fe4 fix: fetch actual Gitea PR head for Codex reviews (#815)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-17 19:44:56 +00:00
jason.woltje fe7a468c9d ci: bake jq into the prebuilt test image (#821)
ci/woodpecker/push/ci-image Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-07-17 19:12:43 +00:00
jason.woltje cabf02e7b9 ci: bake git into the prebuilt test image (#819)
ci/woodpecker/push/ci-image Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-07-17 18:11:16 +00:00
jason.woltje 9ddc6fbda8 feat(fleet): mosaic fleet regen — regenerate roster-derived projections (PR3 of #791) (#813)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-17 03:17:55 +00:00
jason.woltje 31607a4af6 feat(mosaic): durable pre-update snapshot + verify net + restore CLI (#791 PR2) (#811)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-17 00:43:18 +00:00
jason.woltje 32a0ffba13 feat(mosaic): manifest-owned upgrade guard so updates never wipe operator config (#791) (#802)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-16 23:01:26 +00:00
jason.woltje 8536454257 fix(glpi): accept HTTP 206 in list wrappers (#807) (#810)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-16 22:47:58 +00:00
jason.woltje 4f29cc604d fix(tmux): correct cross-socket sender identity (#808) (#809)
ci/woodpecker/push/publish Pipeline was canceled
ci/woodpecker/push/ci Pipeline was canceled
2026-07-16 22:47:25 +00:00
jason.woltje 3be443c96d feat(mosaic): claudex isolated config + env-inject + yolo wiring (P2–P4 of #790) (#806)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-16 22:10:33 +00:00
jason.woltje 59f5f51ffd feat(mosaic): claudex proxy preflight + lifecycle (P1 of #790) (#793)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-16 21:15:33 +00:00
jason.woltje 9745bc3f29 feat(fleet): add reviewed v1-to-v2 migration preview (#788)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-16 13:11:16 +00:00
jason.woltje adad486b6f fix(fleet): enforce exact comms authority (#787)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-16 00:32:23 +00:00
jason.woltje c1aecfabe9 test(fleet): cover reconciler lifecycle gates (#786)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-15 16:46:13 +00:00
jason.woltje 499090508e feat(fleet): reconcile local roster state (#785)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-15 15:03:31 +00:00
jason.woltje c593a15ef8 docs(kbn): freeze KBN-101 database role split contract (#774)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-15 13:34:29 +00:00
jason.woltje bc5e73629e feat(fleet): add generation-guarded agent CRUD (#773)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-15 12:03:05 +00:00
jason.woltje 191efaefeb feat(fleet): enforce generated environment boundary (#772)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-15 08:40:32 +00:00
jason.woltje e9c4aa3e8b test(fleet): validate shipped artifact dispositions (#770)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-15 01:37:12 +00:00
jason.woltje a5e8e55401 feat(fleet): add shared role semantics (#768)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-15 00:53:47 +00:00
jason.woltje eb4e14ae5c feat(mos): add logical identity connector fencing (#757)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-07-14 23:33:06 +00:00
jason.woltje 2e2280070a docs(#753): clear KBN-010 threat and schema gate (#765)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-14 21:46:44 +00:00
jason.woltje aa5b43bba2 feat(fleet): add roster v2 structural compiler (#764)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-14 20:37:52 +00:00
jason.woltje ba13c08890 Fixes #756 (#763)
ci/woodpecker/push/ci-image Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was canceled
2026-07-14 20:26:15 +00:00
jason.woltje c32d85a337 docs(fleet): define declarative configuration M0 (#760)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-14 19:53:12 +00:00
jason.woltje 48b2bc42c9 docs(mos): format Option 2 qualification report (#762)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-14 19:33:09 +00:00
jason.woltje 5e832049bb docs(mos): preserve Option 2 qualification evidence (#759)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline failed
2026-07-14 19:16:11 +00:00
jason.woltje 49e8a54105 docs(#751): Publish native Kanban/SOT canon (#752)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-14 17:08:09 +00:00
jason.woltje d077183554 docs(tess): remediate M5 qualification findings (#750)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-07-13 19:59:38 +00:00
jason.woltje 405984af5a De-hardcode orchestrator and interaction agent names (#748)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-07-13 18:59:27 +00:00
jason.woltje 8dd4e9d541 docs(tess): ledger sync m4 — M5-003 done, #745/#746 merged (#749)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-13 18:14:24 +00:00
jason.woltje bc8016c831 docs(#744): complete Tess documentation gate (#746)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-13 17:44:17 +00:00
jason.woltje e72388b2cb docs(tess): ledger sync m3 — M5-001 + M5-002 done (#745)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-13 16:14:23 +00:00
jason.woltje 6345dbfcf2 feat(agent): add Matrix native runtime provider (#744)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-07-13 15:29:37 +00:00
jason.woltje c6e3cfbd95 docs(tess): ledger sync — W-001 3-of-3 merged, M5-002 approved, M5-001 in TDD (#743)
ci/woodpecker/push/publish Pipeline was canceled
ci/woodpecker/push/ci Pipeline was canceled
2026-07-13 15:29:33 +00:00
jason.woltje 5789711ee0 docs(tess): add migration evidence set (#742)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-13 15:14:29 +00:00
jason.woltje f40e6ba388 docs(tess): sync M4 tracking to merged reality (M4 in-progress / gate-pending) (#741)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-13 15:00:15 +00:00
jason.woltje b7b0f508e6 feat(gateway): register Hermes runtime provider (#740)
ci/woodpecker/push/publish Pipeline failed
ci/woodpecker/push/ci Pipeline was successful
2026-07-13 14:45:08 +00:00
jason.woltje 3378b857eb feat(memory): bind operator plugin to agent sessions (#739)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-07-13 13:44:20 +00:00
jason.woltje e2376190e5 feat(gateway): expose Mos coordination boundary (#737)
ci/woodpecker/push/ci Pipeline is pending
ci/woodpecker/push/publish Pipeline is pending
2026-07-13 13:14:44 +00:00
jason.woltje cca6aaf947 feat(agent): add Hermes transitional capability matrix (#738)
ci/woodpecker/push/ci Pipeline is pending
ci/woodpecker/push/publish Pipeline is pending
2026-07-13 13:14:43 +00:00
jason.woltje 2363f155b4 feat(memory): add operator retrieval plugin (#736)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-07-13 12:44:31 +00:00
jason.woltje 76325ca3f2 feat(tess): add Mos coordination boundary (#735)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-07-13 11:59:16 +00:00
jason.woltje 9e5b9188ce feat(agent): add transitional Hermes runtime adapter (#734)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was canceled
2026-07-13 11:29:27 +00:00
jason.woltje f1c6b37b46 fix(tess): route bare Discord approvals (#733)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-07-13 10:29:10 +00:00
jason.woltje 0b621660c8 feat(tess): wire durable interaction surfaces (#732)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was canceled
2026-07-13 10:05:29 +00:00
jason.woltje 84d884b932 feat(#709): add configured Discord interaction binding (#730)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-07-13 09:02:45 +00:00
jason.woltje 8246ee0137 feat(tess): add generic interaction CLI (#731)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-07-13 05:52:41 +00:00
jason.woltje 99a2d0fc9d feat(tess): persist durable session state (#729)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-07-13 05:14:11 +00:00
jason.woltje e3b5113be2 feat(tess): add configurable Pi interaction service (#728)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-13 02:59:27 +00:00
jason.woltje 24b07d0f83 docs(tess): sync M1 ledger to merged state; M1-V Mos-owned (#727)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-13 02:14:13 +00:00
jason.woltje 86a50138a9 feat(tess): add safe runtime observability (#726)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-07-13 01:29:18 +00:00
jason.woltje 7b9f40d3b7 fix(tess): redact chat persistence and egress (#725)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was canceled
2026-07-13 01:14:16 +00:00
jason.woltje 9a8a572fcf feat(tess): add roster-bound tmux fleet provider (#724)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was canceled
2026-07-13 00:59:24 +00:00
jason.woltje 753a360517 fix(#707): scope session GC retention (#720)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was canceled
2026-07-13 00:44:19 +00:00
jason.woltje e92186d768 feat: add Tess runtime provider registry (#722)
ci/woodpecker/push/ci-image Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-07-12 23:53:54 +00:00
jason.woltje 119f64e69d feat(#707): secure Discord service ingress (#716)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-07-12 23:18:29 +00:00
jason.woltje 46ca3ce742 fix(tess): enforce command authorization approvals (#718)
ci/woodpecker/push/publish Pipeline was canceled
ci/woodpecker/push/ci Pipeline was canceled
2026-07-12 23:18:01 +00:00
jason.woltje 227b73fcdf fix(security): enforce Tess MCP server identity (#717)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-07-12 22:49:00 +00:00
jason.woltje a959b1d6b4 ci: restrict push-event CI to protected branches (halve feature-branch load) (#721)
ci/woodpecker/push/ci Pipeline is pending
ci/woodpecker/push/publish Pipeline is pending
2026-07-12 22:48:58 +00:00
jason.woltje 62f8177806 feat(tess): define runtime provider contract (#719)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was canceled
2026-07-12 22:29:21 +00:00
jason.woltje 353e43c947 fix: enforce Tess session ownership scope (#715)
ci/woodpecker/push/ci Pipeline is pending
ci/woodpecker/push/publish Pipeline is pending
2026-07-12 22:14:17 +00:00
jason.woltje ca9c2b5c23 restore Tess markdown formatting gate (v2, non-author) (#714)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-07-12 21:32:16 +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 59e49cfd15 docs(tess): define Pi-native interaction agent mission (#712)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline failed
2026-07-12 18:09:54 +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 193331544d fix(wizard): honor MOSAIC_GATEWAY_SKIP_NPM_INSTALL — unblock install.sh --dev gateway testing (#698)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-07-10 01:30:10 +00:00
jason.woltje 4e9e053800 fix(tools/tmux): unique per-invocation paste buffer; track auto-submit-drafts.sh (#697)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-09 17:37:40 +00:00
jason.woltje 851c67c27b docs(bootstrap): add python-is-python3 to agent-host prerequisites (#694)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-07-03 09:38:40 +00:00
jason.woltje 495f73bfdb fix(wizard): avoid rerunning completed setup steps (#692)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-06-25 18:44:35 +00:00
jason.woltje b96cc7982a fix(wizard): report gateway failures before success summary (#691)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-06-25 18:14:40 +00:00
jason.woltje 0883fb91ec fix(wizard): resolve skills sync script path (#690)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-06-25 17:35:19 +00:00
jason.woltje 56787fabf1 fix(gateway): disable Redis consumers on local tier (#689)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-06-25 17:17:24 +00:00
jason.woltjeandClaude Opus 4.8 940ae3cc41 feat(installer): prefer npm next lane (#688)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
--next now prefers a fast npm @next install (CLI + gateway from the Gitea registry) and falls back to source build at next if the dist-tag is unavailable. Registry lane gated to non-dev, non-explicit-ref next installs; CLI/gateway prerelease versions must share a pipeline suffix. Adds tools/install-next-lane.test.sh (wired into CI). PR-event CI 1635 fully green + review-of-record APPROVE (functional install test, head 2fd7cfc3).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-25 07:14:24 +00:00
jason.woltjeandClaude Opus 4.8 c25a551c28 ci(#462): add durable next publish pipeline (#687)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
Durable @next integration-line publish: on next pushes, compute <patch+1>-next.<pipeline#> prerelease versions (in-CI, uncommitted) and publish @mosaicstack/* under the next dist-tag; gateway image sha-only on next. Strict guardrails: next-only, never writes latest, never tags from next; main path unchanged. PR-event CI 1631 fully green + review-of-record APPROVE (head b1a887a2). Guardrails independently verified.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-25 05:45:09 +00:00
jason.woltjeandClaude Opus 4.8 94d6538061 feat(installer): add next integration lane (#686)
ci/woodpecker/push/ci Pipeline was successful
Add --next installer flag (build-from-source at the next integration branch; MOSAIC_NEXT=1 env equiv; explicit --ref wins). Three-lane install docs (stable @latest / --next prerelease / --dev source) + @next dist-tag pipeline design doc. Green PR-event CI 1626 + review-of-record APPROVE (head 3a5c12a5).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-25 05:14:32 +00:00
jason.woltjeandClaude Opus 4.8 a3c1ab923c test(#462): add federation M3 integration coverage (#685)
ci/woodpecker/push/ci Pipeline was successful
FED-M3-10 integration tests for the federation M3 verbs (list/get/scope). Test-infra + docs only; green PR-event CI 1623 (all steps incl ci-postgres).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-25 04:14:56 +00:00
jason.woltjeandClaude Opus 4.8 838701bde2 feat(#462): add federation get verb (#683)
ci/woodpecker/push/ci Pipeline was successful
FED-M3-06 get verb. Trust boundary mirrors M3-05 AND-intersect (note returned only when owned by subject AND on an authorized mission). Reviewed (review-of-record APPROVE, head 80a259b2) + green PR-event CI 1620.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-25 03:44:54 +00:00
jason.woltje 86e106fcc9 feat(#462): add federation list verb (#682)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-06-25 02:15:17 +00:00
jason.woltje 67135d3822 fix(fleet): guard mosaic fleet restart against tight-loop re-entry race (#680)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-06-25 01:44:48 +00:00
jason.woltje adb153428b feat(installer): --dev flag builds CLI + gateway from source (#681)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-06-24 23:54:52 +00:00
jason.woltje c739256a2c feat(#462): add federation scope enforcement service (#672)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-06-24 23:22:46 +00:00
jason.woltje fc2970916f style(federation): re-run prettier on TASKS.md (unblock format:check) (#679)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-06-24 22:51:22 +00:00
jason.woltje 79eae2ffce fix(fleet): raise fleet-personas.spec timeout to 30s (mirror #665) (#677)
ci/woodpecker/push/ci Pipeline is pending
ci/woodpecker/push/publish Pipeline is pending
2026-06-24 22:16:49 +00:00
jason.woltje 7035cd23bf docs(federation): record M3-07/09 merges + fix M3-11 dependency DAG (#678)
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/push/publish Pipeline was successful
2026-06-24 21:44:57 +00:00
jason.woltje 6b94d014a8 feat(#462): add federation capabilities verb (#674)
ci/woodpecker/push/ci Pipeline is pending
ci/woodpecker/push/publish Pipeline is pending
2026-06-24 21:39:56 +00:00
jason.woltje 838c44086c feat(#462): add federation query source routing (#673)
ci/woodpecker/push/ci Pipeline is pending
ci/woodpecker/push/publish Pipeline is pending
2026-06-24 21:39:45 +00:00
jason.woltje 3eeed04e17 docs(federation): sync M3 backlog to origin/main reality (#671)
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/push/publish Pipeline was successful
2026-06-24 21:15:14 +00:00
jason.woltje e0e7be70f5 chore(release): @mosaicstack/mosaic 0.0.48 (#670)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-06-24 20:01:17 +00:00
jason.woltje d7eaa19380 feat(fleet): provision roster from system-type profile (H3) (#665)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-06-24 19:48:54 +00:00
jason.woltje 248193cd3b fix(fleet): export MOSAIC_AGENT_CLASS into the agent pane so personas inject (#669)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-06-24 19:38:15 +00:00
jason.woltje a9857c5043 fix(release): republish @mosaicstack/db 0.0.4 with BacklogService; mosaic 0.0.47 (#668)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-06-24 18:54:33 +00:00
jason.woltje e4ede69144 chore(release): mosaic 0.0.46 (persona contracts live) (#666)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-06-24 18:29:01 +00:00
jason.woltje a8008138c8 docs(fleet): record per-agent model switch in north star (#667)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-06-24 18:14:37 +00:00
jason.woltje 0d17a29ebe feat(fleet): export MOSAIC_AGENT_CLASS into agent env (A3a) (#663)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-06-24 17:19:59 +00:00
jason.woltje 28cfecda94 feat(fleet): inject persona contract at launch (A3b) (#664)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline failed
2026-06-24 17:06:51 +00:00
jason.woltje 6c84ccd0b1 feat(fleet): dedicated orchestrator persona, split from planner (#662)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-06-24 16:42:23 +00:00
jason.woltje 84d2757817 feat(fleet): update-surviving persona customization (H4) (#661)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-06-24 16:21:01 +00:00
jason.woltje a738ac1410 feat(fleet): system-type profiles (H2) (#660)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-06-24 16:02:25 +00:00
jason.woltje 538f0556d5 feat(fleet): cross-domain baseline persona library (H1) (#659)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-06-24 15:31:56 +00:00
jason.woltje a094c86eea feat(fleet): North Star scope — general-purpose system, personas & system profiles (workstream H) (#658)
ci/woodpecker/push/publish Pipeline was canceled
ci/woodpecker/push/ci Pipeline was canceled
2026-06-24 15:25:57 +00:00
jason.woltje f852250419 feat(fleet): native Mosaic backlog on @mosaicstack/db (atomic claim + TTL) (#657)
ci/woodpecker/push/ci-image Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was canceled
2026-06-24 14:55:10 +00:00
jason.woltje 61b1bdac2a feat(fleet): add machine-readable NORTH_STAR.yaml + Markdown projection (#656)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-06-24 14:40:09 +00:00
jason.woltje cabb179d5a feat(fleet): seed role registry markdown library (#655)
ci/woodpecker/push/publish Pipeline was canceled
ci/woodpecker/push/ci Pipeline was canceled
2026-06-24 14:39:54 +00:00
jason.woltje eb795bab18 chore(release): mosaic CLI 0.0.45 (#654)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-06-24 14:11:33 +00:00
jason.woltje 937077f6be fix(fleet): report idle agents as available, reserve stuck for genuine blocks (#653)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-06-24 13:58:22 +00:00
jason.woltje 1020cfaf9b chore(release): mosaic CLI 0.0.44 (#652)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-06-24 06:49:04 +00:00
jason.woltje 70661e3fab fix(fleet): derive pane idle from window activity fallback (#651)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-06-24 06:37:45 +00:00
jason.woltje ec8dd7ca86 chore(release): mosaic CLI 0.0.43 (#650)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-06-24 06:08:20 +00:00
jason.woltje d887555852 feat(fleet): classify agent readiness in fleet ps (#649)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-06-24 05:55:47 +00:00
jason.woltje e3adc6a1bc chore(release): mosaic CLI 0.0.42 (#648)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-06-24 05:28:28 +00:00
jason.woltje aa27c42129 fix(fleet): pre-trust claude agent workdir to clear the folder-trust gate (#644) (#645)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-06-24 05:16:46 +00:00
jason.woltje 16ae809442 fix(update): re-seed framework on version drift, not just in-command updates (#642) (#646)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-06-24 05:04:34 +00:00
jason.woltje 6980e40e51 fix(db): stop pglite migration tests flaking CI (timeout + WASM OOM) (#647)
ci/woodpecker/push/ci Pipeline was canceled
ci/woodpecker/push/publish Pipeline was canceled
2026-06-24 05:04:28 +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 4da87640e8 feat(tmux): agent-send.sh --class triage tag for the comms daemon (#552)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-06-23 03:25:16 +00:00
jason.woltje a38a491403 chore(release): mosaic CLI 0.0.41 (#640)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-06-23 02:21:04 +00:00
jason.woltje 78d67c6261 chore(ci): bump ci-base image node 22 → 24-alpine (#639)
ci/woodpecker/push/ci-image Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-06-23 00:59:39 +00:00
jason.woltje 94e5cd7a81 ci: eliminate cold pnpm install via pre-baked CI base image (Phase 1) (#635)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-06-22 22:50:21 +00:00
jason.woltje 4e84f8e850 feat(fleet): comms-block emitter + FLEET-LAUNCH runbook (#633) (#638)
ci/woodpecker/push/ci Pipeline was canceled
ci/woodpecker/push/publish Pipeline was canceled
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-06-22 22:23:50 +00:00
jason.woltje cf8ceb3095 CI: add pre-baked ci-base image (producer) [Phase 1a] (#637)
ci/woodpecker/push/ci-image Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was canceled
2026-06-22 22:20:48 +00:00
jason.woltje bf2a6745c8 fix(install): preserve user fleet data on re-seed + refresh active units (CRITICAL) (#632)
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-06-22 21:38:09 +00:00
jason.woltje d539d61e0e refactor(fleet): rename tmux socket mosaic-factory → mosaic-fleet (#630)
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-06-22 21:08:43 +00:00
jason.woltje 3f69d45334 docs(fleet): consolidate north-star doctrine (budget + control plane + identity) (#629)
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-06-22 21:08:41 +00:00
jason.woltje e2336bb0ca chore(release): mosaic CLI 0.0.40 (#624)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-06-22 19:49:45 +00:00
jason.woltje 7342415a32 fix(fleet): consume model_hint + fix socket-default trap (stand-up fixes) (#627)
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-06-22 19:18:01 +00:00
jason.woltje 095e19443b feat(fleet): onboarding-injection — comms cheat-sheet + peer roster per agent (#621)
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-06-22 17:54:54 +00:00
jason.woltje fabc413407 feat(fleet): F4 Phase 2a — Matrix CS-API connector client + factory (#618)
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-06-22 16:48:17 +00:00
jason.woltje 858d90329d feat(fleet): F4 Phase 1 — chat connector abstraction + Matrix design (#617)
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-06-22 16:14:32 +00:00
jason.woltje 2bf66136e4 feat(fleet): enhancer role + two-agent floor (orchestrator + enhancer) (#615)
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-06-22 13:15:59 +00:00
jason.woltje 4434c3c481 docs(fleet): orchestrator+enhancer two-agent floor + role library + Discord plugin north-star (#613)
ci/woodpecker/push/publish Pipeline was canceled
ci/woodpecker/push/ci Pipeline was canceled
2026-06-22 13:15:05 +00:00
jason.woltje dd0a0d38c6 ci(publish): gate kaniko image builds + publish on changed paths (CI throughput) (#619)
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-06-22 13:14:31 +00:00
jason.woltje d46ac40890 fix(fleet): boot-survival symmetry — disable-on-remove + add-enable + init-R5 (#612)
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-22 08:12:58 +00:00
jason.woltje 8ddd48c843 feat(mosaic): mosaic update re-seeds framework + relaunches agents (R13) (#610)
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-22 03:34:05 +00:00
jason.woltje 528700ceea feat(framework): P6 — docs + compliance matrix + resident-budget CI (#607)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was canceled
ci/woodpecker/tag/publish Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-06-22 02:20:35 +00:00
jason.woltje 32f4215461 chore(release): bump @mosaicstack/mosaic 0.0.38 -> 0.0.39 (#608)
ci/woodpecker/push/ci Pipeline is pending
ci/woodpecker/push/publish Pipeline is pending
2026-06-22 02:16:12 +00:00
jason.woltje 23343bb7f0 feat(mosaic): P5 — overlay composer (compose-contract + *.local overlays) (#605)
ci/woodpecker/push/ci Pipeline is pending
ci/woodpecker/push/publish Pipeline is pending
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-06-22 02:16:05 +00:00
jason.woltje c8b2dab0ca chore(release): bump @mosaicstack/mosaic 0.0.37 -> 0.0.38 (#603)
ci/woodpecker/push/publish Pipeline was canceled
ci/woodpecker/push/ci Pipeline was canceled
2026-06-22 01:48:27 +00:00
jason.woltje 6dbe452a9f fix(fleet): watch viewer-session leak + workdir test settle-race (#601)
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-06-22 01:43:21 +00:00
jason.woltje 59c755067e feat(fleet): F3-m2 — native Pi heartbeat + model surface + mosaic_mission_status tool (#602)
ci/woodpecker/push/ci Pipeline is pending
ci/woodpecker/push/publish Pipeline is pending
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-06-22 01:43:18 +00:00
jason.woltje 6ffb27787e fix(fleet): complete HB reader/writer consistency + sidecar hardening (#599)
ci/woodpecker/push/ci Pipeline was canceled
ci/woodpecker/push/publish Pipeline was canceled
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-06-22 01:22:35 +00:00
jason.woltje 130837365f chore(release): bump @mosaicstack/mosaic 0.0.36 -> 0.0.37 (#597)
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/push/publish Pipeline was successful
2026-06-21 23:27:14 +00:00
jason.woltje 67df06f1c4 feat(fleet): orchestrator-mutable fleet — fleet add/remove (F5/R9) (#596)
ci/woodpecker/push/ci Pipeline is pending
ci/woodpecker/push/publish Pipeline is pending
2026-06-21 23:26:21 +00:00
jason.woltje 60a309d5a4 fix(fleet): heartbeat consistency — MOSAIC_HOME path + configurable interval (#595)
ci/woodpecker/push/ci Pipeline is pending
ci/woodpecker/push/publish Pipeline is pending
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-06-21 23:25:53 +00:00
jason.woltje 2dc0f24828 docs(fleet): Fleet Suite PRD (init/configure/operate + Mos-on-Discord) (#588)
ci/woodpecker/push/ci Pipeline is pending
ci/woodpecker/push/publish Pipeline is pending
2026-06-21 23:17:10 +00:00
jason.woltje 31e7a4d25e docs(framework): P4.1 — fix stale install.sh comments + cmp-equal early-exit (#593)
ci/woodpecker/push/ci Pipeline is pending
ci/woodpecker/push/publish Pipeline is pending
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-06-21 23:12:31 +00:00
jason.woltje ca19d57bba feat(fleet): config-type presets + AI-free init wizard (F1) (#591)
ci/woodpecker/push/ci Pipeline is pending
ci/woodpecker/push/publish Pipeline is pending
2026-06-21 23:07:41 +00:00
jason.woltje bb7d549080 feat(framework): P4 — upgrade-safe Constitution migration (both installers) (#590)
ci/woodpecker/push/ci Pipeline is pending
ci/woodpecker/push/publish Pipeline is pending
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-06-21 23:03:48 +00:00
jason.woltje 5bef2c35eb feat(fleet): fleet ps surfaces unmanaged socket sessions (#586)
ci/woodpecker/push/ci Pipeline was canceled
ci/woodpecker/push/publish Pipeline was canceled
2026-06-21 22:37:34 +00:00
jason.woltje 2849a8f9db chore(release): bump @mosaicstack/mosaic 0.0.35 -> 0.0.36 (#585)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-06-21 21:46:15 +00:00
jason.woltje 7ced5588c9 feat(fleet): launcher heartbeat sidecar — HB for all runtimes (pi/claude/codex) (#584)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was canceled
2026-06-21 21:14:20 +00:00
jason.woltje afcbbb302f feat(fleet): auto-enable units on install + drift recognizes wrapped runtimes (#583)
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/push/publish Pipeline was successful
2026-06-21 20:02:19 +00:00
jason.woltje c2c0b5fe8d chore(release): bump @mosaicstack/mosaic 0.0.34 -> 0.0.35 (#582)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-06-21 18:59:39 +00:00
jason.woltje c9cfe36204 docs(framework): P3.1 fast-follow — governance wording + gate scope + bare-launch note (#577)
ci/woodpecker/push/ci Pipeline was canceled
ci/woodpecker/push/publish Pipeline was canceled
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-06-21 18:56:50 +00:00
jason.woltje fc90c89913 fix(fleet): durable runtime PATH for detached agent launch (#581)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-06-21 17:30:40 +00:00
jason.woltje af2eede7a9 feat(fleet): Phase-2 observability — fleet ps + watch + send verify (#579)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-06-21 04:23:51 +00:00
jason.woltje 5118be74cb feat(framework): P3 — extract Constitution (L0) + gut AGENTS dispatcher (#575)
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 03:20:32 +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 b354bc8fae docs(framework): add agency & persistence patterns to config + guides (#543)
ci/woodpecker/push/ci Pipeline was canceled
ci/woodpecker/push/publish Pipeline was canceled
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-06-21 01:43:36 +00:00
jason.woltje e834bbb83c fix(fleet): install executable tmux helpers (#568)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-06-20 22:27:46 +00:00
jason.woltje 7498fcb20d fix(fleet): preserve agent env overrides on install (#567)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-06-20 21:50:46 +00:00
jason.woltje 42d081613f chore(release): bump mosaic cli to 0.0.32 (#566)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-06-20 21:15:25 +00:00
jason.woltje b5c1381e45 fix(fleet): harden operator sends for release (#565)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-06-20 20:41:11 +00:00
jason.woltje 6dfd78f643 feat(fleet): add local canary CLI (#563)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-06-20 17:49:01 +00:00
jason.woltje 45e2c2aad8 docs: plan durable tmux fleet install (#557)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-06-20 16:19:19 +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 87f561c1f8 fix(launch): include Pi native skill roots in 'all' mode; dedup 'discover' force-loads (#556)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-06-19 19:58:09 +00:00
jason.woltje 8c45857859 feat(launch): force-load fleet-critical Pi skills + reconcile skill docs (#555)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-06-19 18:31:02 +00:00
jason.woltje 63e77887a8 feat: add mosaic-tools skill (fleet toolkit fast path) (#1) 2026-06-19 18:30:58 +00:00
jason.woltje 605221d42f docs(framework/tools): lead TOOLS.md with high-salience fleet-tools cheatsheet (#554)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was canceled
2026-06-19 18:03:03 +00:00
jason.woltje ee584ab48c fix(framework/tools): prettier-format woodpecker README — restore main format gate (#553)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-06-18 22:39:35 +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 b8807e60df feat(agent-reflection): durable kernel — reflection.v1 capture + risk-floor + Phase-0 (#545)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-06-16 21:35:40 +00:00
jason.woltje c461380a4a feat(mosaic-as): agent registration + scoped/revocable tokens (US-007) (#541)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-06-16 01:10:44 +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 bd9527c033 docs(framework): canonize merge-authority policy (hard gate 13 + E2E gate note) (#537)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-06-11 23:56:20 +00:00
jason.woltje aa221bf92e release(mosaic): bump @mosaicstack/mosaic 0.0.30 -> 0.0.31 (#534)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/tag/publish Pipeline was successful
2026-06-11 19:55:43 +00:00
jason.woltje 799df40f4e feat(appservice): room provisioning (M4c) (#535)
ci/woodpecker/push/publish Pipeline was canceled
ci/woodpecker/push/ci Pipeline was canceled
2026-06-11 19:50:55 +00:00
jason.woltje b79e9f32c6 chore(framework): canonize Vault-as-SSOT + ESO-default secrets policy (#519)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-06-11 19:07:00 +00:00
jason.woltje 89d69eb23b docs: add mission control and coordination resilience docs (#511)
ci/woodpecker/push/ci Pipeline was canceled
ci/woodpecker/push/publish Pipeline was canceled
2026-06-11 19:06:35 +00:00
jason.woltje 59b611ba8a refactor(framework): thin-core prompt diet — cut injected contract ~53% (#529)
ci/woodpecker/push/ci Pipeline was canceled
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
2026-06-11 18:10:42 +00:00
jason.woltje dfa0be42f6 feat(framework/tools): inter-agent tmux comms — agent-send.sh + addressing standard (#533)
ci/woodpecker/push/ci Pipeline was canceled
ci/woodpecker/push/publish Pipeline was canceled
2026-06-11 18:01:44 +00:00
jason.woltje bb96a3f23e ci: publish mosaic-as appservice image (#532)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-06-10 23:00:38 +00:00
jason.woltje 48b2f28e45 feat(appservice): mosaic-as daemon host + container (M4a) (#531)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-06-10 22:16:28 +00:00
jason.woltje 8f09c910a9 feat(appservice): Matrix Application Service core library (M4a) (#530)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-06-10 21:23:25 +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 755df9079e Merge pull request 'fix(db): bootstrap migrations on local-tier gateway startup' (#510) from fix/db-bootstrap-migrations into main 2026-05-04 22:13:14 +00:00
jason.woltjeandClaude Opus 4.7 ac5650d9f9 fix(db): bootstrap migrations on local-tier gateway startup
Fresh `mosaic gateway install` (npm) left the gateway DB schema empty —
sign-in 500'd with `relation "users" does not exist`, and every entry
point (auth, bootstrap setup) failed because they all query the users
table first. Five stacked bugs on the local (PGlite) tier:

1. `packages/db/package.json` `files: ["dist"]` excluded the `drizzle/`
   SQL migrations from the published tarball.
2. `runMigrations()` only supports postgres-js — unusable for embedded
   PGlite.
3. `apps/gateway/src/database/database.module.ts` never invoked
   migrations at startup.
4. `createPgliteDb` didn't load pgvector, so migration 0001's
   `CREATE EXTENSION vector` failed.
5. Drizzle's PG migrator wraps every migration in one outer
   transaction, which trips Postgres' `check_safe_enum_use` on
   migration 0009 (`ALTER TYPE ADD VALUE 'pending'` → `SET DEFAULT
   'pending'` in the same tx).

Changes:
- Ship `drizzle/` in the published tarball.
- `createPgliteDb` loads `@electric-sql/pglite/vector`.
- New `runPgliteMigrations(handle)` walks the Drizzle journal and
  runs each statement-breakpoint chunk through PGlite's `client.exec()`
  (autocommit per statement). Records into `drizzle.__drizzle_migrations`
  for interop with the postgres-js path. Per-statement try/catch
  surfaces which statement of which migration failed.
- `DatabaseModule` runs migrations in `OnModuleInit` before
  `app.listen()`. Local tier: explicit `runPgliteMigrations` then
  `storageAdapter.migrate()`. Postgres tier: just `storageAdapter.migrate()`,
  which already calls `runMigrations(url)` internally — no double-call.
- Removed `packages/storage/src/test-utils/pglite-with-vector.ts`. The
  "intentionally not exported" rationale is moot now that migration
  0001 forces pgvector load anyway. The integration test uses
  `createPgliteDb` + `runPgliteMigrations` from `@mosaicstack/db`.

Tests: BetterAuth tables exist after migrate; idempotent (re-runs 0009);
partial-failure surfaces statement-level context and leaves no ledger row.

QA on a fresh PGlite install:
- `Applying PGlite schema migrations...` then `Initializing storage
  adapter (pglite)...` in startup log.
- `GET /api/bootstrap/status` → `{"needsSetup":true}` HTTP 200 (was 500).
- `POST /api/bootstrap/setup` reaches Zod validator (was 500).

Scope: this PR fixes the local (PGlite) tier. Postgres-tier first
install still has the outer-transaction problem and a journal ordering
bug (0009's `when` < 0008's). Documented inline as TODO and in the
scratchpad — needs a separate change with real-Postgres validation.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
2026-05-04 17:06:50 -05:00
jason.woltje bd83f86740 Merge pull request 'feat(federation): mTLS AuthGuard with OID-based grant resolution (FED-M3-03)' (#509) from feat/federation-m3-auth-guard into main
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-25 13:27:20 +00:00
jarvisandClaude Sonnet 4.6 0af3e218a1 fix(federation/auth-guard): remediate CRIT-1/CRIT-2 + HIGH-1..4 review findings
ci/woodpecker/pr/ci Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
- CRIT-1: Validate cert subjectUserId against grant.subjectUserId from DB;
  use authoritative DB value in FederationContext
- CRIT-2: Add @Inject(GrantsService) decorator (tsx/esbuild requirement)
- HIGH-1: Validate UTF8String TLV tag, length, and bounds in OID parser
- HIGH-2: Collapse all 403 wire messages to a generic string to prevent
  grant enumeration; keep internal logger detail
- HIGH-3: Assert federation wire envelope shape in all guard tests
- HIGH-4: Regression test for subjectUserId cert/DB mismatch

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-04-25 06:33:37 -05:00
jarvisandClaude Sonnet 4.6 b01c9b3bb0 feat(federation): mTLS AuthGuard with OID-based grant resolution (FED-M3-03)
Adds FederationAuthGuard that validates inbound mTLS client certs on
federation API routes. Extracts custom OIDs (grantId, subjectUserId),
loads the grant+peer from DB in one query, asserts active status, and
validates cert serial as defense-in-depth. Attaches FederationContext
to requests on success and uses federation wire-format error envelopes
(not raw NestJS exceptions) for 401/403 responses.

New files:
- apps/gateway/src/federation/oid.util.ts — shared OID extraction (no dupe ASN.1 logic)
- apps/gateway/src/federation/server/federation-auth.guard.ts — guard impl
- apps/gateway/src/federation/server/federation-context.ts — FederationContext type + module augment
- apps/gateway/src/federation/server/index.ts — barrel export
- apps/gateway/src/federation/server/__tests__/federation-auth.guard.spec.ts — 11 unit tests

Modified:
- apps/gateway/src/federation/grants.service.ts — adds getGrantWithPeer() with join
- apps/gateway/src/federation/federation.module.ts — registers FederationAuthGuard as provider

Closes #462

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-04-25 06:33:37 -05:00
jason.woltje b67f2c9f08 Merge pull request 'feat(federation): outbound mTLS FederationClient (FED-M3-08)' (#508) from feat/federation-m3-client into main
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-24 04:30:29 +00:00
jarvisandClaude Sonnet 4.6 37675ae3f2 fix(federation/client): serialize cache fills, destroy evicted Agent, cover env-var guard
ci/woodpecker/pr/ci Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
- HIGH-A: resolveEntry now uses promise-cache pattern so concurrent
  callers serialize on a single in-flight build, eliminating duplicate
  key material in heap and duplicate DB round-trips
- HIGH-B: flushPeer destroys the evicted undici Agent so stale TLS
  connections close on cert rotation
- MED-C: add regression test for PEER_MISCONFIGURED when
  STEP_CA_ROOT_CERT_PATH is unset

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-04-23 22:56:57 -05:00
jarvisandClaude Opus 4.7 a4a6769a6d fix(federation/client): pin Step-CA root, fix lockfile, harden cache test
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
CRIT-1: regenerate pnpm-lock.yaml so apps/gateway resolves [email protected].6
(prior PR pushed package.json without lockfile update; CI failed with
ERR_PNPM_OUTDATED_LOCKFILE). Incidentally cleans 57 lines of stale
peer-dep entries.

CRIT-2: cache-hit test no longer swallows resolveEntry errors. Calls the
private method directly twice and asserts identity equality plus a
single DB select, removing the silent-failure path the prior assertion
allowed.

HIGH-1: mTLS Agent now pins Step-CA root via STEP_CA_ROOT_CERT_PATH.
Without the env var resolveEntry throws PEER_MISCONFIGURED, refusing to
dial peers against the public trust store. PEM is read once and cached
on the service instance.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-04-23 22:30:09 -05:00
jarvisandClaude Sonnet 4.6 21650fb194 feat(federation): outbound mTLS FederationClient (FED-M3-08)
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/pr/ci Pipeline failed
Implements FederationClientService — a NestJS injectable that dials peer
gateways over mTLS (undici Agent with cert+sealed-key from federation_peers),
invokes list/get/capabilities verbs, validates responses via Zod, and surfaces
all failure modes as typed FederationClientError with a coherent error code
taxonomy (PEER_NOT_FOUND, PEER_INACTIVE, PEER_MISCONFIGURED, NETWORK,
FORBIDDEN, HTTP_{status}, INVALID_RESPONSE).

Per-peer Agent instances are cached in a Map for the service lifetime;
flushPeer(peerId) invalidates the cache for M5/M6 cert rotation and
revocation events.

Wired into FederationModule providers + exports so QuerySourceService
(M3-09) can inject it.

13 unit tests covering all required scenarios via undici MockAgent +
real sealClientKey/unsealClientKey round-trip.

Closes #462

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-04-23 22:16:52 -05:00
jason.woltje 89c733e0b9 feat(federation): two-gateway test harness scaffold (FED-M3-02) (#505)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-24 03:01:25 +00:00
jason.woltje ee3f2defd9 feat(types): federation v1 DTOs (FED-M3-01) (#506)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-04-24 02:54:40 +00:00
jason.woltje 7342c1290d fix(federation): use real PEM certs in enrollment + ca service tests (#507)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-04-24 02:43:42 +00:00
jason.woltje e64ddd2c1c docs(federation): M3 mission planning — 14-task decomposition (#504)
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/push/publish Pipeline was successful
2026-04-24 01:13:40 +00:00
jason.woltje 4ece6dc643 chore(federation): M2 milestone close (FED-M2-13) (#503)
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/tag/publish Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-22 06:09:54 +00:00
jason.woltje 194c3b603e docs(federation): M2 Step-CA setup guide + admin CLI reference (FED-M2-12) (#502)
ci/woodpecker/push/publish Pipeline failed
ci/woodpecker/push/ci Pipeline failed
2026-04-22 06:06:45 +00:00
jason.woltje fc1600b738 fix(federation): security hardening — OID verification, atomic activation, audit on failure (#501)
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/push/publish Pipeline failed
2026-04-22 06:02:52 +00:00
jason.woltje 0ee5b14c68 test(federation): M2 E2E peer-add enrollment flow (FED-M2-10) (#500)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-22 05:37:06 +00:00
jason.woltje 3eee176cc3 test(federation): M2 integration tests (FED-M2-09) (#499)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-22 05:08:24 +00:00
jason.woltje 74fe60d8d6 feat(federation): admin controller + CLI federation commands (FED-M2-08) (#498)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-22 04:39:46 +00:00
jason.woltje 0bfaa56e9e feat(federation): enrollment controller + single-use token flow (FED-M2-07) (#497)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-22 04:23:19 +00:00
jason.woltje 01dd6b9fa1 feat(federation): grants service CRUD + status transitions (FED-M2-06) (#496)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-22 03:57:12 +00:00
jason.woltje 1038ae76e1 feat(federation): Step-CA client service for grant certs (FED-M2-04) (#494)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-22 03:34:37 +00:00
jason.woltje bf082d95a0 feat(federation): seal federation peer client keys at rest (FED-M2-05) (#495)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-22 03:10:20 +00:00
jason.woltje bb24292cf7 fix(federation): healthcheck + restart policy for federated-test stacks (#492)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-22 02:56:40 +00:00
jason.woltje f2cda52e1a fix(deploy): bump gateway image digest to sha-9f1a081 [DEPLOY-IMG-FIX] (#491)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
2026-04-22 02:35:19 +00:00
jason.woltje 7d7cf012f0 feat(federation): scope schema validator [FED-M2-03] (#489)
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/push/publish Pipeline failed
2026-04-22 02:31:13 +00:00
jason.woltje c56dda74aa feat(federation): Step-CA sidecar in federated compose [FED-M2-02] (#490)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-04-22 02:21:49 +00:00
jason.woltje 9f1a08185e docs(federation): S21 tracking — DEPLOY-01/02 done, IMG-FIX in flight, M2-01 in remediation (#487)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-22 02:02:36 +00:00
jason.woltje d2e408656b fix(docker): pnpm deploy for self-contained gateway runtime image (#488)
ci/woodpecker/push/publish Pipeline failed
ci/woodpecker/push/ci Pipeline failed
2026-04-22 02:02:29 +00:00
jason.woltje 54c278b871 feat(db): federation schema — grants/peers/audit_log [FED-M2-01] (#486)
ci/woodpecker/push/publish Pipeline failed
ci/woodpecker/push/ci Pipeline failed
2026-04-22 02:02:21 +00:00
jason.woltje 4dbd429203 feat(deploy): portainer stack template for federation test instances [DEPLOY-02] (#485)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
2026-04-22 01:34:44 +00:00
jason.woltje b985d7bfe2 docs(federation): M2 mission planning — TASKS decomposition + manifest update (#483)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-04-22 01:24:00 +00:00
jason.woltje 45e8f02c91 feat(mosaic-portainer): PORTAINER_INSECURE flag for self-signed TLS (#484)
ci/woodpecker/push/publish Pipeline failed
ci/woodpecker/push/ci Pipeline failed
2026-04-22 01:21:54 +00:00
jason.woltje 54c422ab06 Merge pull request 'docs(federation): close FED-M1 milestone' (#481) from feat/federation-m1-close into main
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/tag/publish Pipeline was successful
2026-04-20 02:20:43 +00:00
jarvis b9fb8aab57 docs(federation): close FED-M1 milestone
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
- TASKS.md: mark FED-M1-12 done with PR/issue/tag references
- MISSION-MANIFEST.md: phase=M1 complete, progress 1/7, M1 row done with PR range #470-#481, session log appended
- scratchpad: Session 19 entry covering M1-09 → M1-12 with PR ledger and M1 retrospective learnings

Refs #460
2026-04-19 21:12:52 -05:00
jason.woltje 78841f228a docs(federation): operator setup + migration guides (FED-M1-11) (#480)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-20 02:07:15 +00:00
jason.woltje dc4afee848 fix(storage): redact credentials in driver errors + advisory lock (FED-M1-10) (#479)
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/push/publish Pipeline failed
2026-04-20 02:02:57 +00:00
jason.woltje 1e2b8ac8de test(federation): standalone regression canary — no breakage from M1 (FED-M1-09) (#478)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-20 01:46:35 +00:00
jason.woltje 15d849c166 test(storage): integration test for migrate-tier (FED-M1-08) + camelCase column fix (#477)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-04-20 01:40:02 +00:00
jason.woltje 78251d4af8 test(federation): integration tests for federated tier gateway boot (FED-M1-07) (#476)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-20 01:13:10 +00:00
jason.woltje 1a4b1ebbf1 feat(gateway,storage): mosaic gateway doctor with tier health JSON (FED-M1-06) (#475)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-20 01:00:39 +00:00
jason.woltje ccad30dd27 feat(storage): mosaic storage migrate-tier with dry-run + idempotency (FED-M1-05) (#474)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-20 00:35:08 +00:00
jason.woltje 4c2b177eab feat(gateway): tier-detector with fail-fast PG/Valkey/pgvector probes (FED-M1-04) (#473)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-20 00:07:07 +00:00
jason.woltje 58169f9979 feat(storage): pgvector adapter support gated on tier=federated (FED-M1-03) (#472)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-19 23:42:18 +00:00
jason.woltje 51402bdb6d feat(infra): docker-compose.federated.yml overlay (FED-M1-02) (#471)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-19 23:21:31 +00:00
jason.woltje 9c89c32684 feat(config): add federated tier + rename team→standalone (FED-M1-01) (#470)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-04-19 23:11:11 +00:00
jason.woltje 8aabb8c5b2 docs(mission): author MVP rollup manifest, archive install-ux-v2 (#469)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-19 22:51:11 +00:00
jason.woltje 66512550df docs(federation): PRD, milestones, mission manifest, and M1 task breakdown (#468)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-19 22:27:09 +00:00
jason.woltje 46dd799548 docs(federation): PRD, milestones, mission manifest, and M1 task breakdown (#467)
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-04-19 22:09:20 +00:00
jason.woltje 5f03c05523 chore(release): @mosaicstack/mosaic 0.0.30 (#459)
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-04-12 02:18:17 +00:00
jason.woltje c3f810bbd1 fix(mosaic): seed TOOLS.md from defaults on install (#458)
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-04-12 02:02:21 +00:00
jason.woltje b2cbf898d7 docs(scratchpad): finalize yolo runtime hotfix evidence (#456)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
Follow-up to mosaicstack/stack#455.

Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-04-11 17:14:00 +00:00
jason.woltje b2cec8c6ba fix(mosaic): stop yolo runtime from leaking runtime name as first user message (#455)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
Fixes mosaicstack/stack#454

Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-04-11 16:57:43 +00:00
jason.woltje 81c1775a03 chore(release): @mosaicstack/mosaic 0.0.29 (#453)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/tag/publish Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-04-08 00:42:54 +00:00
jason.woltje f64ec12f39 fix(installer): preserve credentials dir and seed STANDARDS.md (#452)
ci/woodpecker/push/publish Pipeline failed
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-04-08 00:40:49 +00:00
jason.woltje 026382325c feat(framework): superpowers enforcement, typecheck hook, file-ownership rules (#451)
ci/woodpecker/manual/ci Pipeline was successful
ci/woodpecker/manual/publish Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-04-07 00:44:22 +00:00
jason.woltje 1bfd8570d6 chore(release): @mosaicstack/mosaic 0.0.28 (#450) 2026-04-06 00:46:31 +00:00
jason.woltje 312acd8bad chore: sweep mosaicstack/mosaic-stack → mosaicstack/stack + add short install URL (#448) 2026-04-06 00:39:56 +00:00
jason.woltje d08b969918 fix(mosaic): mask password input in TUI login prompt (#449) 2026-04-06 00:33:54 +00:00
jason.woltje 051de0d8a9 docs: update README for mosaicstack/stack repo rename (#447) 2026-04-06 00:22:20 +00:00
jason.woltje bd76df1a50 feat(mosaic): drill-down main menu + provider-first flow + quick start (#446) 2026-04-06 00:15:23 +00:00
jason.woltje 62b2ce2da1 docs: orchestrator close-out IUV-M02 (#445)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-05 23:50:55 +00:00
jason.woltje 172bacb30f feat(mosaic): IUV-M02 — CORS/FQDN UX polish + skill installer rework (#444)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-04-05 23:44:07 +00:00
jason.woltje 43667d7349 docs: orchestrator close-out IUV-M01 — mark tasks done, append session 2 (#443)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-05 22:40:08 +00:00
jason.woltje 783884376c docs: mark IUV-M01 complete — mosaic-v0.0.26 released (#436) (#442)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-04-05 22:31:37 +00:00
jason.woltje c08aa6fa46 fix: add vitest.config.ts to eslint allowDefaultProject (#440 build fix) (#441)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/tag/publish Pipeline was successful
2026-04-05 22:01:57 +00:00
jason.woltje 0ae932ab34 fix: bootstrap hotfix — DTO erasure, wizard failure, port prefill, Pi SDK copy (mosaic-v0.0.26) (#440)
ci/woodpecker/push/publish Pipeline failed
ci/woodpecker/push/ci Pipeline was successful
2026-04-05 21:43:30 +00:00
jason.woltje a8cd52e88c docs: scaffold install-ux-v2 mission (#439)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-05 21:27:19 +00:00
jason.woltje a4c94d9a90 chore(release): @mosaicstack/mosaic 0.0.25 (#435)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/tag/publish Pipeline was successful
2026-04-05 20:53:19 +00:00
jason.woltje cee838d22e docs: close out install-ux-hardening mission (#434)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-05 19:19:54 +00:00
jason.woltje 732f8a49cf feat: unified first-run flow — merge wizard + gateway install (IUH-M03) (#433)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-04-05 19:13:02 +00:00
jason.woltje be917e2496 docs: mark IUH-M02 complete, start IUH-M03 (#432)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-05 18:02:21 +00:00
jason.woltje cd8b1f666d feat: wizard remediation — password mask, hooks preview, headless (IUH-M02) (#431)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-05 17:47:53 +00:00
jason.woltje 8fa5995bde docs: scaffold install-ux-hardening mission + archive cli-unification (#430)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-05 17:15:39 +00:00
jason.woltje 25cada7735 feat: mosaic uninstall (IUH-M01) (#429)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-05 17:06:21 +00:00
jason.woltje be6553101c docs: finalize CLI unification mission at mosaic-v0.0.24 (#424)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-05 14:54:48 +00:00
jason.woltje 417805f330 fix: bump memory/queue/storage to 0.0.4 to force republish (#423)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/tag/publish Pipeline was successful
2026-04-05 14:39:15 +00:00
jason.woltje 2472ce52e8 fix: bump stale sub-package versions (brain/forge/log) (#422)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-05 14:26:30 +00:00
jason.woltje 597eb232d7 fix: revert mosaic to 0.0.22 alpha + republish macp (#421)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-05 14:15:46 +00:00
jason.woltje afe997db82 docs: mission cli-unification-20260404 complete (#420)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-05 07:54:50 +00:00
jason.woltje b9d464de61 docs: CLI unification release v0.1.0 (M8) (#419)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
ci/woodpecker/tag/publish Pipeline was successful
2026-04-05 07:46:00 +00:00
jason.woltje 872c124581 feat(mosaic): unified first-run UX wizard -> gateway install -> verify (#418)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-05 07:29:17 +00:00
jason.woltje a531029c5b feat(mosaic): mosaic telemetry command (M6 CU-06-01..05) (#417)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-05 07:06:42 +00:00
jason.woltje 35ab619bd0 docs: session 2 orchestrator bookkeeping (M3/M4/M5 complete) (#416)
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/push/publish Pipeline failed
2026-04-05 07:06:40 +00:00
jason.woltje 831193cdd8 fix(macp): align exports + add CLI smoke test (#415)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-04-05 06:57:42 +00:00
jason.woltje df460d5a49 feat(macp): mosaic macp CLI surface (#410)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-05 06:33:52 +00:00
jason.woltje 119ff0eb1b fix(mosaic): gateway token recovery review remediations (#414)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-05 06:13:29 +00:00
jason.woltje 3abd63ea5c Merge pull request 'feat(mosaic): mosaic auth CLI surface' (#413) from feat/mosaic-auth-cli into main
ci/woodpecker/push/publish Pipeline failed
ci/woodpecker/push/ci Pipeline failed
2026-04-05 06:11:33 +00:00
jason.woltje 641e4604d5 feat(forge): mosaic forge CLI surface (#412)
ci/woodpecker/push/publish Pipeline failed
ci/woodpecker/push/ci Pipeline failed
2026-04-05 06:08:50 +00:00
jarvisandClaude Sonnet 4.6 9b5ecc0171 feat(mosaic): add auth command and stage parallel agent changes
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
Picks up auth command and spec written by parallel agent, and updated
mosaic cli.ts wiring from parallel development during cli-unification.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-04-05 00:58:03 -05:00
jarvisandClaude Sonnet 4.6 a00325da0e feat(forge): add registerForgeCommand for mosaic forge CLI surface
Adds mosaic forge run|status|resume|personas list subcommands to
@mosaicstack/forge, wires registerForgeCommand into the root mosaic CLI,
and ships a smoke test asserting command structure. Ref CU-05-01
cli-unification-20260404.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-04-05 00:58:03 -05:00
jason.woltje 4ebce3422d feat(log): mosaic log CLI surface (#407)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-04-05 05:57:22 +00:00
jason.woltje 751e0ee330 feat(storage): mosaic storage CLI surface (#405)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-04-05 05:48:13 +00:00
jason.woltje 54b2920ef3 feat(memory): mosaic memory CLI surface (#406)
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/push/publish Pipeline failed
2026-04-05 05:44:06 +00:00
jason.woltje 5917016509 feat(mosaic): gateway token recovery via BetterAuth cookie (#411)
ci/woodpecker/push/ci Pipeline is pending
ci/woodpecker/push/publish Pipeline is pending
2026-04-05 05:43:49 +00:00
jason.woltje 7b4f1d249d feat(mosaic): top-level mosaic config command (#408)
ci/woodpecker/push/publish Pipeline failed
ci/woodpecker/push/ci Pipeline failed
2026-04-05 05:37:05 +00:00
jason.woltje 5425f9268e feat(queue): mosaic queue CLI surface (#404)
ci/woodpecker/push/publish Pipeline failed
ci/woodpecker/push/ci Pipeline failed
2026-04-05 05:27:59 +00:00
jason.woltje febd866098 feat(brain): mosaic brain CLI surface (#403)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-04-05 05:20:44 +00:00
jason.woltje 2446593fff feat(mosaic): alphabetize and group mosaic --help output (#402)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-04-05 05:12:32 +00:00
jason.woltje 651426cf2e docs(plan): gateway admin token recovery flow (#401)
ci/woodpecker/push/publish Pipeline failed
ci/woodpecker/push/ci Pipeline failed
2026-04-05 05:11:33 +00:00
jason.woltje cf46f6e0ae docs: capture planning decisions + session 1 handoff (#400)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-05 04:57:00 +00:00
jason.woltje 6f15a84ccf docs: archive stale mission, scaffold CLI unification mission (#399)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-05 04:47:54 +00:00
jason.woltje c39433c361 chore: remove legacy @mosaicstack/cli package (#398)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-04-05 04:39:46 +00:00
jason.woltje 257796ce87 Merge pull request 'chore: bump @mosaicstack/mosaic to 0.0.21 for republish' (#397) from chore/bump-mosaic-0.0.21 into main
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-05 04:12:05 +00:00
jarvis 2357602f50 chore: bump @mosaicstack/mosaic to 0.0.21 for publish
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
2026-04-04 23:09:52 -05:00
jason.woltje 1230f6b984 ci: fail publish pipeline loudly on registry/auth/network errors (#396)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-05 03:58:35 +00:00
jason.woltje 14b775f1b9 Merge pull request 'fix: populate KNOWN_PACKAGES for mosaic update command' (#395) from fix/populate-known-packages-list into main
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
Reviewed-on: http://git.mosaicstack.dev/mosaicstack/mosaic-stack/pulls/395
2026-04-05 03:52:57 +00:00
jarvis c7691d9807 fix: populate KNOWN_PACKAGES with all workspace packages for 'mosaic update'
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
- Remove @mosaicstack/cli (absorbed into @mosaicstack/mosaic)
- Add all 21 remaining workspace packages so the multi-package
  update checker actually covers every published package
2026-04-04 22:49:45 -05:00
jason.woltje 9a53d55678 Merge pull request 'fix: update Gitea org references from mosaic/ to mosaicstack/' (#394) from fix/gitea-org-rename into main
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
Reviewed-on: http://git.mosaicstack.dev/mosaicstack/mosaic-stack/pulls/394
2026-04-05 03:35:11 +00:00
jarvis 31008ef7ff fix: update Gitea org references from mosaic/ to mosaicstack/
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
- Update all package.json repo URLs (mosaic/mosaic-stack → mosaicstack/mosaic-stack)
- Update npm registry URLs (/api/packages/mosaic/npm → /api/packages/mosaicstack/npm)
- Update woodpecker publish destinations
- Update tools/install.sh registry and repo base URLs
2026-04-04 22:31:20 -05:00
jason.woltje 621ab260c0 fix(mosaic): resumable gateway install + prominent admin token (#393)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/manual/publish Pipeline failed
ci/woodpecker/manual/ci Pipeline failed
2026-04-05 03:19:07 +00:00
jason.woltje 2b1840214e Merge pull request 'fix: rename @mosaic/* packages to @mosaicstack/*' (#392) from fix/rename-mosaic-scope-391 into main
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-04-05 03:11:55 +00:00
jarvis 5cfccc2ead fix(mosaic): remove unused hasUpdate variable in formatAllPackagesTable
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
Fixes lint error:
@typescript-eslint/no-unused-vars on hasUpdate
2026-04-04 22:01:01 -05:00
jarvis 774b76447d fix: rename all packages from @mosaic/* to @mosaicstack/*
ci/woodpecker/pr/ci Pipeline failed
ci/woodpecker/push/ci Pipeline failed
- Updated all package.json name fields and dependency references
- Updated all TypeScript/JavaScript imports
- Updated .woodpecker/publish.yml filters and registry paths
- Updated tools/install.sh scope default
- Updated .npmrc registry paths (worktree + host)
- Enhanced update-checker.ts with checkForAllUpdates() multi-package support
- Updated CLI update command to show table of all packages
- Added KNOWN_PACKAGES, formatAllPackagesTable, getInstallAllCommand
- Marked checkForUpdate() with @deprecated JSDoc

Closes #391
2026-04-04 21:43:23 -05:00
jason.woltje 80994bdc8e fix(packages): bump db/memory/queue for PGlite + adapter factories (#389)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-05 02:20:23 +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 255ba46a4d fix(packages): republish @mosaic/config and bump dependents (#386)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-05 01:56:57 +00:00
jason.woltje 10285933a0 fix: retarget updater to @mosaic/mosaic (#384)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-04-05 01:52:30 +00:00
jason.woltje 543388e18b fix(mosaic): resolve framework scripts via import.meta.url (#385)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
Fixes #383 — resolveTool now uses fileURLToPath(import.meta.url). Adds package.json/framework subpath exports. Bumps @mosaic/mosaic to 0.0.18.
2026-04-05 01:41:46 +00:00
jason.woltje 07a1f5d594 Merge pull request 'feat(mosaic): merge @mosaic/cli into @mosaic/mosaic' (#381) from fix/merge-cli-into-mosaic into main
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-05 01:11:33 +00:00
jarvis c6fc090c98 feat(mosaic): merge @mosaic/cli into @mosaic/mosaic
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
@mosaic/mosaic is now the single package providing both:
- 'mosaic' binary (CLI: yolo, coord, prdy, tui, gateway, etc.)
- 'mosaic-wizard' binary (installation wizard)

Changes:
- Move packages/cli/src/* into packages/mosaic/src/
- Convert dynamic @mosaic/mosaic imports to static relative imports
- Add CLI deps (ink, react, socket.io-client, @mosaic/config) to mosaic
- Add jsx: react-jsx to mosaic's tsconfig
- Exclude packages/cli from workspace (pnpm-workspace.yaml)
- Update install.sh to install @mosaic/mosaic instead of @mosaic/cli
- Bump version to 0.0.17

This eliminates the circular dependency between @mosaic/cli and
@mosaic/mosaic that was blocking the build graph.
2026-04-04 20:07:27 -05:00
jason.woltje 9723b6b948 chore: bump @mosaic/cli and @mosaic/mosaic to 0.0.16 (#379)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-05 00:52:09 +00:00
jason.woltje c0d0fd44b7 refactor(storage): replace better-sqlite3 with PGlite adapter (#378)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-04 21:58:14 +00:00
jason.woltje 30c0fb1308 fix: remediate npm deprecation warnings in @mosaic/gateway 0.0.3 (#377)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-04 21:03:54 +00:00
jason.woltje 26fac4722f fix: gateway install preserves npm prefix via registry flag (#376)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-04 20:36:15 +00:00
jason.woltje e3f64c79d9 chore: move gateway default port from 4000 to 14242 (#375)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-04 20:17:40 +00:00
jason.woltje cbd5e8c626 fix: scope Gitea registry to @mosaic packages only (#374)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-04 19:09:14 +00:00
jason.woltje 7560c7dee7 fix: gateway install uses Gitea registry instead of npmjs (#373)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-04-04 18:59:40 +00:00
jason.woltje 982a0e8f83 chore: bump @mosaic/mosaic and @mosaic/cli to 0.0.11 (#372)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-04 18:47:03 +00:00
jason.woltje fc7fa11923 feat: local tier gateway with PGlite + Gitea-only publishing (#371)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-04-04 18:39:20 +00:00
jason.woltje 86d6c214fe feat: gateway publishability + npmjs publish script (#370)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-04 18:07:05 +00:00
jason.woltje 39ccba95d0 feat: mosaic gateway CLI daemon management + admin token auth (#369)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-04-04 18:03:12 +00:00
jason.woltje 202e375f41 Merge pull request 'fix: add build tools to CI install step for better-sqlite3 native bindings' (#368) from feat/task-1775219952-fix-add-build-tools-to-ci-install-step-for-better-sqlite3 into main
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-03 15:41:23 +00:00
jarvis d0378c5723 fix: add Alpine build tools before pnpm install in CI
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/pr/ci Pipeline failed
2026-04-03 09:13:25 -05:00
jason.woltje d6f04a0757 Merge pull request 'fix: add build tools to CI install step for better-sqlite3 native bindings' (#366) from fix/storage-sqlite-ci into main
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-03 13:41:04 +00:00
jason.woltje afedb8697e Merge pull request 'fix: allow better-sqlite3 build script in pnpm 10' (#367) from fix/pnpm-build-scripts into main
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-03 13:11:07 +00:00
jarvis 1274df7ffc fix: allow better-sqlite3 build script in pnpm 10
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
2026-04-03 08:06:01 -05:00
jarvis 1b4767bd8b fix: add build tools to CI install step for better-sqlite3 native bindings
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/pr/ci Pipeline failed
2026-04-03 07:41:39 -05:00
jason.woltje 0b0fe10b37 Merge pull request 'feat: storage abstraction retrofit — adapters for queue, storage, memory (phases 1-4)' (#365) from feat/storage-abstraction into main
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/push/publish Pipeline was successful
2026-04-03 04:40:57 +00:00
jason.woltje acfb31f8f6 fix: quality-rails Commander version mismatch + installer defaults (#364)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-03 02:40:02 +00:00
jarvis fd83bd4f2d chore(orchestrator): Phase 4 complete — config schema + CLI lifecycle commands
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/pr/ci Pipeline failed
381 tests passing (347 gateway + 34 CLI), 40/40 tasks clean
2026-04-02 21:38:40 -05:00
jarvisandClaude Opus 4.6 ce3ca1dbd1 feat(cli): add gateway start/stop/status lifecycle commands
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-04-02 21:37:20 -05:00
jarvisandClaude Opus 4.6 95e7b071d4 feat(cli): add mosaic gateway init command with tier selection wizard
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-04-02 21:35:32 -05:00
jason.woltje d4c5797a65 fix: installer copies default framework files (AGENTS.md) to mosaicHome (#363)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-04-03 02:34:43 +00:00
jason.woltje 70a51ba711 fix: all CLI script resolution uses bundled-first resolveTool() (#362)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-04-03 02:28:07 +00:00
jason.woltje db8023bdbb fix: fwScript prefers npm-bundled scripts over stale deployed copies (#361)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-04-03 02:21:58 +00:00
jason.woltje 9e597ecf87 chore: bump @mosaic/mosaic and @mosaic/cli to 0.0.6 (#360)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-04-03 02:13:37 +00:00
jason.woltje a23c117ea4 fix: auto-migrate customized skills to skills-local/ on sync (#359)
ci/woodpecker/push/publish Pipeline failed
ci/woodpecker/push/ci Pipeline failed
2026-04-03 02:11:03 +00:00
jason.woltje 0cf80dab8c fix: stale update banner + skill sync dirty worktree crash (#358)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-04-03 02:04:05 +00:00
jarvisandClaude Opus 4.6 04a80fb9ba feat(config): add MosaicConfig schema + loader with tier auto-detection
ci/woodpecker/push/ci Pipeline failed
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-04-02 21:03:00 -05:00
jarvis 626adac363 chore(orchestrator): Phase 3 complete — local tier implemented (SQLite + keyword search + JSON queue)
ci/woodpecker/push/ci Pipeline failed
42 new tests: 4 queue, 18 storage, 20 memory
347 total tests passing
2026-04-02 20:56:39 -05:00
jarvisandClaude Opus 4.6 35fbd88a1d feat(memory): implement keyword search adapter — no vector dependency
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-04-02 20:55:00 -05:00
jason.woltje 381b0eed7b Merge pull request 'chore: bump @mosaic/mosaic and @mosaic/cli to 0.0.4' (#357) from chore/bump-0.0.4 into main
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
Reviewed-on: http://git.mosaicstack.dev/mosaic/mosaic-stack/pulls/357
2026-04-03 01:51:55 +00:00
jarvisandClaude Opus 4.6 25383ea645 feat(storage): implement SQLite adapter with better-sqlite3
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-04-02 20:51:13 -05:00
jarvis e7db9ddf98 chore: bump @mosaic/mosaic and @mosaic/cli to 0.0.4
ci/woodpecker/pr/ci Pipeline failed
ci/woodpecker/push/ci Pipeline failed
2026-04-02 20:50:44 -05:00
jarvisandClaude Opus 4.6 7bb878718d feat(queue): implement local adapter with JSON persistence
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-04-02 20:46:11 -05:00
jarvis 46a31d4e71 chore(orchestrator): Phase 2 complete — existing backends wrapped as adapters
ci/woodpecker/push/ci Pipeline was successful
2026-04-02 20:44:11 -05:00
jarvisandClaude Opus 4.6 e128a7a322 feat(gateway): wire adapter factories + DI tokens alongside existing providers
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-04-02 20:44:11 -05:00
jarvisandClaude Opus 4.6 27b1898ec6 refactor(memory): wrap pgvector logic as MemoryAdapter implementation
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-04-02 20:44:11 -05:00
jarvisandClaude Opus 4.6 d19ef45bb0 feat(storage): implement Postgres adapter wrapping Drizzle + @mosaic/db
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-04-02 20:44:10 -05:00
jarvisandClaude Opus 4.6 5e852df6c3 refactor(queue): wrap ioredis as bullmq adapter behind QueueAdapter interface
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-04-02 20:44:10 -05:00
jarvis e0eca771c6 chore(orchestrator): Phase 1 complete — all interfaces defined 2026-04-02 20:44:10 -05:00
jarvisandClaude Opus 4.6 9d22ef4cc9 feat: add adapter factory + registry pattern for queue, storage, memory
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-04-02 20:44:10 -05:00
jarvisandClaude Opus 4.6 41961a6980 feat(memory): define MemoryAdapter interface types
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-04-02 20:44:10 -05:00
jarvisandClaude Opus 4.6 e797676a02 feat(storage): define StorageAdapter interface types + scaffold package
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-04-02 20:44:10 -05:00
jarvisandClaude Opus 4.6 05d61e62be feat(queue): define QueueAdapter interface types
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-04-02 20:44:10 -05:00
jarvis 73043773d8 chore(orchestrator): Bootstrap storage abstraction retrofit
Mission: Decouple gateway from hardcoded Postgres/Valkey backends.
20 tasks across 5 phases. Estimated total: ~214K tokens.

Phase 1: Interface extraction (4 tasks)
Phase 2: Wrap existing backends as adapters (5 tasks)
Phase 3: Local tier implementation (4 tasks)
Phase 4: Config + CLI commands (4 tasks)
Phase 5: Migration + docs (3 tasks)
2026-04-02 20:44:10 -05:00
jason.woltje 0be9729e40 Merge pull request 'fix: syncDirectory same-path guard, nested .git exclusion, and sync stash handling' (#356) from fix/idempotent-init into main
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
Reviewed-on: http://git.mosaicstack.dev/mosaic/mosaic-stack/pulls/356
2026-04-03 01:42:18 +00:00
jarvis e83674ac51 fix: mosaic sync — auto-stash dirty worktree before pull --rebase
ci/woodpecker/pr/ci Pipeline failed
ci/woodpecker/push/ci Pipeline was successful
git pull --rebase fails with 'cannot pull with rebase: You have
unstaged changes' when the skills repo has local modifications.

Fix: detect dirty index/worktree, stash before pull, restore after.
Also gracefully handle pull failures (warn and continue with existing
checkout) and stash pop conflicts.
2026-04-02 20:41:11 -05:00
jarvis a6e59bf829 fix: syncDirectory — guard same-path copy and skip nested .git dirs
Two bugs causing 'EACCES: permission denied, copyfile' when source
and target are the same path (e.g. wizard with sourceDir == mosaicHome):

1. No same-path guard — syncDirectory tried to copy every file onto
   itself; git pack files are read-only (0444) so copyFileSync fails.
2. excludeGit only matched top-level .git — nested .git dirs like
   sources/agent-skills/.git were copied, hitting the same permission
   issue.

Fixes:
- Early return when resolve(source) === resolve(target)
- Match .git dirs at any depth via dirName and relPath checks
- Skip files inside .git/ paths

Added file-ops.test.ts with 4 tests covering all cases.
2026-04-02 20:41:11 -05:00
jason.woltje e46f0641f6 Merge pull request 'fix: make mosaic init idempotent — detect existing config files' (#355) from fix/idempotent-init into main
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
Reviewed-on: http://git.mosaicstack.dev/mosaic/mosaic-stack/pulls/355
2026-04-03 01:30:01 +00:00
jarvis 07efaa9580 chore: bump @mosaic/mosaic and @mosaic/cli to 0.0.3
ci/woodpecker/pr/ci Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-04-02 20:26:01 -05:00
jarvis 361fece023 fix: make mosaic init idempotent — detect existing config files
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/pr/ci Pipeline failed
- mosaic-init bash script: detect existing SOUL.md/USER.md/TOOLS.md and
  prompt user to keep, import (re-use values as defaults), or overwrite.
  Non-interactive mode exits cleanly unless --force is passed.
  Overwrite creates timestamped backups before replacing files.

- launch.ts checkSoul(): prefer 'mosaic wizard' over legacy bash script
  when SOUL.md is missing, with fallback to mosaic-init.

- detect-install.ts: pre-populate wizard state with existing values when
  user chooses 'reconfigure', so they see current settings as defaults.

- soul-setup.ts: show existing agent name and communication style as
  defaults during reconfiguration.

- Added tests for reconfigure pre-population and reset non-population.
2026-04-02 20:20:59 -05:00
jason.woltje 80e69016b0 Merge pull request 'chore: bump all packages to 0.0.2 — drop alpha prerelease tag' (#354) from chore/bump-0.0.2 into main
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
Reviewed-on: http://git.mosaicstack.dev/mosaic/mosaic-stack/pulls/354
2026-04-03 01:12:24 +00:00
jarvis e084a88a9d chore: bump all packages to 0.0.2 — drop alpha prerelease tag
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
Switches from 0.0.1-alpha.2 to 0.0.2. Clean semver, no prerelease
suffixes. We're still alpha (0.0.x range).
2026-04-02 20:03:55 -05:00
jason.woltje 990a88362f Merge pull request 'feat: complete CLI command parity — coord, prdy, seq, upgrade' (#352) from fix/complete-cli-parity into main
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
Reviewed-on: http://git.mosaicstack.dev/mosaic/mosaic-stack/pulls/352
2026-04-03 00:52:36 +00:00
jarvis ea9782b2dc feat: complete CLI command parity — add coord, prdy, seq, upgrade
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
The #351 merge landed before the force-push with full commands.
This adds the missing subcommands:

- mosaic coord {init,status,mission,continue,run,smoke,resume}
  → delegates to tools/orchestrator/*.sh with --claude/--codex/--pi/--yolo
- mosaic prdy {init,update,validate,status}
  → delegates to tools/prdy/*.sh with --claude/--codex/--pi
- mosaic seq {check,fix,start}
  → sequential-thinking MCP management (native TS)
- mosaic upgrade {release,check,project}
  → delegates to tools/_scripts/mosaic-release-upgrade and mosaic-upgrade

Also removes duplicate prdy registration (was in both launch.ts and
the old registerPrdyCommand — now only in launch.ts).
2026-04-02 19:51:34 -05:00
jason.woltje 8efbaf100e Merge pull request 'feat: unify mosaic CLI — single binary, no PATH conflict' (#351) from feat/unify-mosaic-cli into main
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-03 00:41:06 +00:00
jarvis 15830e2f2a feat!: unify mosaic CLI — native launcher, no bin/ directory
ci/woodpecker/pr/ci Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
BREAKING CHANGE: ~/.config/mosaic/bin/ is removed entirely.
The mosaic npm CLI is now the only executable.

## What changed

- **bin/ → deleted**: All scripts moved to tools/_scripts/ (internal)
- **mosaic-launch → deleted**: Launcher logic is native TypeScript
  in packages/cli/src/commands/launch.ts
- **mosaic.ps1 → deleted**: PowerShell launcher removed
- **Framework install.sh**: Complete rewrite with migration system
- **Version tracking**: .framework-version file (schema v2)
- **Migration v1→v2**: Auto-removes bin/, cleans old PATH entries
  from shell profiles

## Native TypeScript launcher (commands/launch.ts)

All runtime launch logic ported from bash:
- Runtime prompt builder (AGENTS.md + RUNTIME.md + USER.md + TOOLS.md)
- Mission context injection (reads .mosaic/orchestrator/mission.json)
- PRD status injection (scans docs/PRD.md)
- Pre-flight checks (MOSAIC_HOME, AGENTS.md, SOUL.md, runtime binary)
- Session lock management with signal cleanup
- Per-runtime launch: Claude, Codex, OpenCode, Pi
- Yolo mode flags per runtime
- Pi skill discovery + extension loading
- Framework management (init, doctor, sync, bootstrap) delegates
  to tools/_scripts/ bash implementations

## Installer

- tools/install.sh: detects framework by .framework-version or AGENTS.md
- Framework install.sh: migration system with schema versioning
- Forward-compatible: add migrations as numbered blocks
- No PATH manipulation for framework (npm bin is the only PATH entry)
2026-04-02 19:37:13 -05:00
jason.woltje 04db8591af Merge pull request 'docs: add project README' (#350) from docs/readme into main
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
Reviewed-on: http://git.mosaicstack.dev/mosaic/mosaic-stack/pulls/350
2026-04-03 00:17:10 +00:00
jarvis 785d30e065 docs: add project README with install, usage, architecture, and dev guide
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
2026-04-02 19:12:28 -05:00
jason.woltje e57a10913d chore: bump all packages to 0.0.1-alpha.2 (#349)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-02 18:21:23 +00:00
jason.woltje 0d12471868 feat: add web search, file edit, MCP management, file refs, and /stop to CLI/TUI (#348)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-02 18:08:30 +00:00
jason.woltje ea371d760d Merge pull request 'feat: unified install.sh + auto-update checker (deprecates mosaic/bootstrap)' (#347) from feat/install-update-checker into main
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-02 05:41:07 +00:00
jarvis 3b9104429b fix(mosaic): wizard integration test — templates path after monorepo migration
ci/woodpecker/pr/ci Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
Templates moved from packages/mosaic/templates/ to
packages/mosaic/framework/templates/ in #345. The test's
existsSync guard silently skipped the copy, causing writeSoul
to early-return without writing SOUL.md.
2026-04-02 00:12:03 -05:00
jarvis 8a83aed9b1 feat: unify install.sh — single installer for framework + npm CLI
- tools/install.sh now installs both components:
  1. Framework (bash launcher, guides, runtime configs) → ~/.config/mosaic/
  2. @mosaic/cli (TUI, gateway client, wizard) → ~/.npm-global/
- Downloads framework from monorepo archive (no bootstrap repo dependency)
- Supports --framework, --cli, --check, --ref flags
- Delete remote-install.sh and remote-install.ps1 (redundant redirectors)
- Update all stale mosaic/bootstrap references → mosaic/mosaic-stack
- Update README.md with monorepo install instructions

Deprecates: mosaic/bootstrap repo
2026-04-02 00:12:03 -05:00
jarvis 2f68237046 fix: remove --registry from npm install to avoid 404 on transitive deps
The @mosaic scope registry is configured in ~/.npmrc. Passing --registry
on the install command overrides the default registry for ALL packages,
causing non-@mosaic deps like @clack/prompts to 404 against Gitea.
2026-04-02 00:11:42 -05:00
jarvis 45f5b9062e feat: install.sh + auto-update checker for CLI
- tools/install.sh: standalone installer/upgrader, curl-pipe safe
  (main() wrapper, process.argv instead of stdin, mkdir -p prefix)
- packages/mosaic/src/runtime/update-checker.ts: version check module
  with 1h cache at ~/.cache/mosaic/update-check.json
- CLI startup: non-blocking background update check on every invocation
- 'mosaic update' command: explicit check + install (--check for CI)
- session-start.sh: warns agents when CLI is outdated
- Proper semver comparison including pre-release precedence
- eslint: allow __tests__ in packages/mosaic for projectService
2026-04-02 00:11:42 -05:00
jason.woltje 147f5f1bec Merge pull request 'fix: remove stale bootstrap repo references' (#346) from fix/stale-bootstrap-refs into main
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/push/publish Pipeline was successful
2026-04-02 02:27:49 +00:00
Jason Woltje f05b198882 fix: remove stale bootstrap repo references from CLI error messages
ci/woodpecker/pr/ci Pipeline failed
ci/woodpecker/push/ci Pipeline failed
Replace 'cd ~/src/mosaic-bootstrap && bash install.sh' with
'npm install -g @mosaic/mosaic' now that bootstrap is archived.
2026-04-01 21:26:53 -05:00
jason.woltje d0a484cbb7 Merge pull request 'feat: complete bootstrap → monorepo migration (archive-ready)' (#345) from feat/framework-migration-complete into main
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/push/publish Pipeline failed
2026-04-02 02:24:33 +00:00
Jason Woltje 6e6ee37da0 feat: complete framework migration — PowerShell, adapters, guides, profiles, tests
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/pr/ci Pipeline failed
Completes the bootstrap repo migration with remaining files:
- PowerShell scripts (.ps1) for Windows support (bin/ + tools/)
- Runtime adapters (claude, codex, generic, pi)
- Guides (17 .md files) and profiles (domains, tech-stacks, workflows)
- Wizard test suite (6 test files from bootstrap tests/)
- Memory placeholder, audit history

Bootstrap repo (mosaic/bootstrap) is now fully superseded:
- All 335 files accounted for
- 5 build config files (package.json, tsconfig, etc.) not needed —
  monorepo has its own at packages/mosaic/
- skills-local/ superseded by monorepo skills/ with mosaic-* naming
- src/ already lives at packages/mosaic/src/
2026-04-01 21:23:26 -05:00
jason.woltje 53199122d8 Merge pull request 'feat: integrate framework files into monorepo' (#344) from feat/framework-into-monorepo into main
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-04-02 02:20:17 +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
jason.woltje f3cb3e6852 Merge pull request 'fix(web): add public/ directory — fixes Docker build COPY failure' (#343) from fix/web-public-dir into main
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
2026-04-01 18:09:40 +00:00
Jason Woltje e599f5fe38 fix(web): add public/ directory — fixes Docker build COPY failure
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
Kaniko fails when COPY --from=builder references a path that doesn't
exist. The web app had no public/ directory, causing build-web to fail
with 'no such file or directory' on the public assets COPY step.
2026-04-01 13:09:03 -05:00
jason.woltje 6357a3fc9c Merge pull request 'fix(ci): use gitea_token secret for npm publish' (#342) from fix/ci-npm-secret into main
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-04-01 17:51:32 +00:00
Jason Woltje 92998e6e65 fix(ci): use gitea_token secret for npm publish
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
2026-04-01 12:51:06 -05:00
jason.woltje 2394a2a0dd Merge pull request 'feat: npm publish pipeline + package versioning (0.0.1-alpha.1)' (#341) from feat/npm-publish-pipeline into main 2026-04-01 17:47:10 +00:00
Jason Woltje 13934d4879 feat: npm publish pipeline + package versioning (0.0.1-alpha.1)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
Publish pipeline:
- Add publish-npm step to .woodpecker/publish.yml — publishes all
  @mosaic/* packages to Gitea npm registry on main push/tag
- Requires gitea_npm_token Woodpecker secret (package:write scope)
- publish-npm runs after build, parallel with Docker image builds
- pnpm publish resolves workspace:* to concrete versions automatically

Package configuration:
- All 20 packages versioned at 0.0.1-alpha.1
- publishConfig added to all packages (Gitea registry, public access)
- files field added to all packages (ship only dist/)
- @mosaic/forge includes pipeline/ assets in published package

Meta package (@mosaic/mosaic):
- Now depends on @mosaic/forge, @mosaic/macp, @mosaic/prdy,
  @mosaic/quality-rails, @mosaic/types
- npm install @mosaic/mosaic pulls in the standalone framework

Build fixes:
- Fix forge and macp tsconfig rootDir: '.' -> 'src' so dist/index.js
  resolves correctly (was dist/src/index.js)
- Exclude __tests__ and vitest.config from build includes
- Clean stale build artifacts from old rootDir config

Required Woodpecker secret:
  woodpecker secret add mosaic/mosaic-stack \
    --name gitea_npm_token --value '<token>' \
    --event push,manual,tag
2026-04-01 12:46:13 -05:00
jason.woltje aa80013811 Merge pull request 'feat: mosaic-* skill naming, board/forge/prdy skills, doctor --fix auto-wiring' (#340) from feat/mosaic-skills-doctor-wiring into main
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-04-01 17:29:39 +00:00
Jason Woltje 2ee7206c3a feat: mosaic-* skill naming, new board/forge/prdy skills, doctor --fix auto-wiring
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
Skills:
- Rename all repo skills to mosaic-<name> convention (jarvis -> mosaic-jarvis, etc.)
- Update frontmatter name: fields to match directory names
- New mosaic-board skill: standalone Board of Directors multi-persona review
- New mosaic-forge skill: standalone Forge specialist pipeline
- New mosaic-prdy skill: PRD lifecycle (init/update/validate/status)

Wizard (packages/mosaic):
- Add mosaic-board, mosaic-forge, mosaic-prdy, mosaic-standards, mosaic-macp
  to RECOMMENDED_SKILLS
- Add new skills to SKILL_CATEGORIES for categorized browsing

Framework scripts (~/.config/mosaic/bin):
- mosaic (launcher): load skills from both skills/ and skills-local/ for Pi
- mosaic-doctor: add --fix flag for auto-wiring skills into all harnesses,
  Pi skill dir checks, Pi settings.json validation, mosaic-* presence checks
- mosaic-sync-skills: add Pi as 4th link target, fix find to follow symlinks
  in skills-local/, harden is_mosaic_skill_name() with -L fallback
- mosaic-link-runtime-assets: add Pi settings.json skills path patching,
  remove duplicate extension copy (launcher --extension is single source)
- mosaic-migrate-local-skills: add Pi to skill_roots, fix find for symlinks

YAML fixes:
- Quote description values containing colons in mosaic-deploy and
  mosaic-woodpecker SKILL.md frontmatter (fixes Pi parse errors)
2026-04-01 12:28:36 -05:00
jason.woltje be74ca3cf9 feat: add Pi as first-class Mosaic runtime (#339)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-04-01 17:02:23 +00:00
jason.woltje 35123b21ce Merge pull request 'fix(ci): pass DATABASE_URL through Turbo to test tasks' (#338) from fix/turbo-env-passthrough into main
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline failed
2026-03-31 04:03:29 +00:00
jason.woltje 492dc18e14 Merge pull request 'fix(db): add missing migration to Drizzle journal — fixes CI test failures' (#337) from fix/ci-drizzle-migration-journal into main
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/push/publish Pipeline failed
2026-03-31 03:03:45 +00:00
jarvis a824a43ed1 fix(ci): pass DATABASE_URL through Turbo to test tasks
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/pr/ci Pipeline failed
2026-03-30 22:02:37 -05:00
jarvis 9b72f0ea14 fix(db): add CREATE EXTENSION vector before first migration using pgvector
ci/woodpecker/pr/ci Pipeline failed
ci/woodpecker/push/ci Pipeline failed
The insights table uses vector(1536) but no migration enables the pgvector
extension. CI postgres (pgvector/pgvector:pg17) has the extension available
but it must be explicitly created before use.

Adds CREATE EXTENSION IF NOT EXISTS vector at the top of
0001_cynical_ultimatum.sql (the first migration referencing vector type).
2026-03-30 21:14:44 -05:00
jarvis d367f00077 fix(db): add missing 0001_cynical_ultimatum to Drizzle migration journal
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/pr/ci Pipeline failed
The migration file 0001_cynical_ultimatum.sql existed on disk but was not
registered in the Drizzle journal (_journal.json). This caused fresh-database
migrations (CI) to skip creating tables (agent_logs, insights, preferences,
skills, summarization_jobs), then 0002_nebulous_mimic.sql would fail trying
to ALTER the non-existent preferences table.

Fix: insert cynical_ultimatum at idx 1 in the journal and shift all
subsequent entries (idx 2-7).

Verified: pnpm test passes (347 tests, 35 tasks).
2026-03-30 21:09:34 -05:00
jason.woltje 31a5751c6c Merge pull request 'feat(ci): Docker build+push pipeline for gateway and web images' (#335) from fix/ci-docker-publish-test-dep into main
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/push/publish Pipeline failed
2026-03-31 01:48:08 +00:00
jason.woltje fa43989cd5 Merge pull request 'fix: parse VALKEY_URL into RedisOptions for BullMQ — fixes ECONNREFUSED 6379' (#336) from fix/bullmq-valkey-url-port into main
ci/woodpecker/push/ci Pipeline failed
2026-03-31 01:45:37 +00:00
jason.woltje 1b317e8a0a style: fix prettier formatting in plugins/macp (consolidation follow-up)
ci/woodpecker/pr/ci Pipeline failed
ci/woodpecker/push/ci Pipeline failed
2026-03-30 20:43:54 -05:00
jason.woltje 316807581c fix: parse VALKEY_URL into RedisOptions object for BullMQ connection
BullMQ v5 RedisConnection constructor does:
  Object.assign({ port: 6379, host: '127.0.0.1' }, opts)

When opts is a URL string (via 'as unknown as ConnectionOptions'),
Object.assign only copies character-index properties from the string,
so the default port 6379 was never overridden — causing ECONNREFUSED
against the wrong port instead of the configured 6380.

Fix: parse VALKEY_URL with new URL() and return a plain RedisOptions
object { host, port, ... } so Object.assign merges it correctly.
2026-03-30 20:42:03 -05:00
jarvis 3321d4575a fix(ci): wait for postgres readiness before migration + tests
ci/woodpecker/pr/ci Pipeline failed
ci/woodpecker/push/ci Pipeline failed
2026-03-30 20:41:46 -05:00
jarvis 85d4527701 fix(macp): use sh instead of bash in gate-runner — Alpine Linux compatibility
ci/woodpecker/pr/ci Pipeline failed
ci/woodpecker/push/ci Pipeline failed
2026-03-30 20:31:39 -05:00
jarvis 47b7509288 fix(ci): add postgres service sidecar for integration tests
ci/woodpecker/pr/ci Pipeline failed
ci/woodpecker/push/ci Pipeline failed
2026-03-30 20:25:59 -05:00
jarvis 34fad9da81 fix(ci): remove build step from ci.yml — build only in publish pipeline
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/pr/ci Pipeline failed
2026-03-30 20:19:29 -05:00
jarvis 48be0aa195 fix(ci): separate publish pipeline — Docker builds independent of test failures
ci/woodpecker/pr/ci Pipeline failed
ci/woodpecker/push/ci Pipeline failed
2026-03-30 20:12:23 -05:00
jarvis f544cc65d2 fix(ci): switch to Kaniko image builder using global gitea secrets
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/pr/ci Pipeline failed
2026-03-30 20:04:50 -05:00
jarvis 41e8f91b2d fix(ci): decouple build/publish from test step — DB test requires external Postgres
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/pr/ci Pipeline failed
2026-03-30 20:00:35 -05:00
jarvis f161e3cb62 feat(ci): add Docker build+push pipeline for gateway and web images
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/pr/ci Pipeline failed
2026-03-30 19:54:28 -05:00
jason.woltje da41724490 Merge pull request 'fix: remove all hardcoded user paths — dynamic OC SDK resolution' (#333) from fix/macp-dynamic-sdk-resolution into main
ci/woodpecker/push/ci Pipeline failed
2026-03-30 19:55:21 +00:00
mos 281e636e4d fix: remove all hardcoded user paths from plugins — dynamic SDK resolution
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/pr/ci Pipeline failed
- plugins/macp/src/index.ts: use createRequire + dynamic import() for OC SDK
- plugins/macp/src/acp-runtime-types.ts: local ACP runtime type definitions
- plugins/macp/src/macp-runtime.ts: DEFAULT_REPO_ROOT and PI_RUNNER_PATH use
  os.homedir() instead of hardcoded /home/user/
- plugins/mosaic-framework/src/index.ts: removed hardcoded SDK import
- No hardcoded /home/ paths remain in any plugin source file
- Plugin works on any machine with openclaw installed globally
2026-03-30 19:55:00 +00:00
jason.woltje 87dcd12a65 Merge pull request 'fix: update MACP plugin paths from /home/jarvis to local environment' (#332) from fix/macp-plugin-paths into main
ci/woodpecker/push/ci Pipeline failed
2026-03-30 19:47:11 +00:00
mos d3fdc4ff54 fix: update MACP plugin paths from /home/jarvis to dynamic resolution
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/pr/ci Pipeline failed
- plugins/macp/src/index.ts: updated OC SDK imports to local paths
- plugins/macp/src/macp-runtime.ts: DEFAULT_REPO_ROOT → mosaic-stack-new, PI_RUNNER_PATH updated
- plugins/macp/openclaw.plugin.json: default repoRoot description updated
- Removed stale tsconfig.tsbuildinfo with old path references
2026-03-30 19:46:52 +00:00
jason.woltje 9690aba0f5 Merge pull request 'feat: monorepo consolidation — forge, MACP, framework plugin, profiles/guides/skills' (#331) from feat/monorepo-consolidation into main
ci/woodpecker/push/ci Pipeline failed
2026-03-30 19:44:23 +00:00
mos 10689a30d2 feat: monorepo consolidation — forge pipeline, MACP protocol, framework plugin, profiles/guides/skills
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/pr/ci Pipeline failed
Work packages completed:
- WP1: packages/forge — pipeline runner, stage adapter, board tasks, brief classifier,
  persona loader with project-level overrides. 89 tests, 95.62% coverage.
- WP2: packages/macp — credential resolver, gate runner, event emitter, protocol types.
  65 tests, 96.24% coverage. Full Python-to-TS port preserving all behavior.
- WP3: plugins/mosaic-framework — OC rails injection plugin (before_agent_start +
  subagent_spawning hooks for Mosaic contract enforcement).
- WP4: profiles/ (domains, tech-stacks, workflows), guides/ (17 docs),
  skills/ (5 universal skills), forge pipeline assets (48 markdown files).

Board deliberation: docs/reviews/consolidation-board-memo.md
Brief: briefs/monorepo-consolidation.md

Consolidates mosaic/stack (forge, MACP, bootstrap framework) into mosaic/mosaic-stack.
154 new tests total. Zero Python — all TypeScript/ESM.
2026-03-30 19:43:24 +00:00
jason.woltje 40c068fcbc Merge pull request 'fix(oc-plugin): MACP OC bridge — route through controller queue instead of Pi-direct' (#330) from fix/macp-oc-bridge into main
ci/woodpecker/push/ci Pipeline failed
2026-03-30 15:48:12 +00:00
jarvis a9340adad7 fix(oc-plugin): replace Pi-direct with MACP controller bridge in runTurn
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/pr/ci Pipeline failed
2026-03-30 10:33:32 -05:00
jason.woltje 5cb72e8ca6 Merge pull request 'feat(oc-plugin): MACP ACP runtime backend — sessions_spawn(runtime:macp)' (#329) from feat/oc-macp-plugin-v2 into main
ci/woodpecker/push/ci Pipeline failed
2026-03-30 04:29:47 +00:00
jarvis 48323e7d6e chore: update pnpm lockfile for plugins/macp
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/pr/ci Pipeline failed
2026-03-29 23:25:36 -05:00
jarvis 01259f56cd feat(oc-plugin): add MACP ACP runtime backend
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/pr/ci Pipeline failed
2026-03-29 23:21:28 -05:00
jason.woltje 472f046a85 chore: Harness Foundation mission COMPLETE — v0.2.0 (#327)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-23 01:29:05 +00:00
jason.woltje dfaf5a52df docs: add M7-003 through M7-007 Matrix architecture sections (#326)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-23 01:26:16 +00:00
jason.woltje 93b3322e45 feat(M5-008,M6-001-005): session hardening tests + BullMQ job queue (#324)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-23 01:21:58 +00:00
jason.woltje a532fd43b2 feat(M6-006,M6-007,M7-001,M7-002): admin jobs API, job event logging, channel adapter interface, message protocol (#325)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-23 01:21:03 +00:00
jason.woltje 701bb69e6c feat(M4-013,M5-001,M5-002,M5-003): routing e2e tests, agent config loading, model+agent switching (#323)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-23 01:09:09 +00:00
jason.woltje 1035d13fc0 feat(M5-004,M5-005,M5-006,M5-007): session-conversation binding, session:info broadcast, agent creation from TUI, and session metrics (#321)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-23 00:58:07 +00:00
jason.woltje b18976a7aa feat(M4-009,M4-010,M4-011): routing rules CRUD, per-user overrides, agent capabilities (#320)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-23 00:48:42 +00:00
jason.woltje 059962fe33 test(M3-012): provider adapter integration tests for all 5 providers (#319)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-23 00:42:00 +00:00
jason.woltje 9b22477643 feat(routing): implement routing decision pipeline — M4-006 (#318)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-23 00:41:04 +00:00
jason.woltje 6a969fbf5f fix(ci)+feat(M3-010/011): skip DB-gated tests in CI + provider_credentials migration (#317)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-23 00:34:31 +00:00
jason.woltje fa84bde6f6 feat(routing): task classifier + default rules + CI test fixes — M4-004/005 (#316)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-23 00:26:49 +00:00
jason.woltje 6f2b3d4f8c feat(M3-005): ZaiAdapter for Z.ai GLM-5 provider (#314)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-23 00:09:16 +00:00
jason.woltje 0ee6bfe9de feat(routing): routing_rules schema + types — M4-001/002/003 (#315)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-23 00:08:56 +00:00
jason.woltje cabd39ba5b chore: update TASKS.md — 25/65 done, Wave 5 in progress (#312)
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/pr/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-23 00:02:14 +00:00
Jarvis 809ca9a1d9 feat: add mosaic ops skills (portainer, gitea, woodpecker, deploy, orchestrator)
- mosaic-portainer: stack list/status/redeploy/logs via Portainer API scripts
- mosaic-gitea: PR/issue/milestone ops for git.mosaicstack.dev
- mosaic-woodpecker: pipeline status, trigger, CI wait
- mosaic-deploy: full end-to-end deploy flow (push → CI → merge → redeploy)
- mosaic-orchestrator: mission init/run/status + worker launch rules
2026-03-22 15:32:05 +00:00
jason.woltje 10761f3e47 feat(providers): OpenRouter adapter + Ollama embedding support — M3-004/006 (#311)
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/pr/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-21 21:38:09 +00:00
jason.woltje 08da6b76d1 feat(M3-003): OpenAI provider adapter for Codex gpt-5.4 (#310)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-21 21:35:43 +00:00
jason.woltje 5d4efb467c feat(M3-002): implement AnthropicAdapter for Claude Sonnet 4.6, Opus 4.6, and Haiku 4.5 (#309)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-21 21:33:55 +00:00
jason.woltje 6c6bcbdb7f feat(M3-007,M3-009): provider health check scheduler and Ollama embedding default (#308)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-21 21:30:15 +00:00
jason.woltje cfdd2b679c chore: M1 + M2 milestones complete — 18/65 tasks done (#307)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-21 21:21:20 +00:00
jason.woltje 34d4dbbabd feat(M3-008): define model capability matrix (#303)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-21 21:19:07 +00:00
jason.woltje 78d591b697 test(M2-007): cross-user data isolation integration test (#305)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-21 21:16:50 +00:00
jason.woltje e95c70d329 feat(M3-001): refactor ProviderService into IProviderAdapter pattern (#306)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-21 21:16:45 +00:00
jason.woltje d8ac088f3a test(persistence): M1-008 verification — 20 integration tests (#304)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-21 21:08:19 +00:00
jason.woltje 0d7f3c6d14 chore: Wave 2 complete — 14/65 tasks done (#302)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-21 21:02:04 +00:00
jason.woltje eddcca7533 feat(gateway): load conversation history on session resume (M1-004, M1-005) (#301)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-21 21:00:13 +00:00
jason.woltje ad06e00f99 feat(conversations): add search endpoint — M1-006 (#299)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-21 20:45:50 +00:00
jason.woltje 5b089392fd fix(security): M2-008 Valkey key audit — SCAN over KEYS, restrict /gc to admin (#298)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-21 20:45:43 +00:00
jason.woltje 02ff3b3256 feat(tui): add /history command — M1-007 (#297)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-21 20:41:27 +00:00
jason.woltje 1d14ddcfe7 chore: Wave 1 complete — fix merge conflicts, update task status (#296)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-21 20:37:27 +00:00
jason.woltje 05a805eeca fix(memory): scope InsightsRepo operations to userId — M2-001/002 (#290)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-21 20:34:42 +00:00
jason.woltje ebf99d9ff7 fix(M2-005,M2-006): enforce user ownership at repo level for conversations and agents (#293)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-21 20:34:11 +00:00
jason.woltje cf51fd6749 chore: mark M1-001/002/003 and M2-003/004 done (#295)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-21 20:22:05 +00:00
jason.woltje bb22857fde fix(security): scope memory tools to session userId — M2-003/004 (#294)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-21 20:19:19 +00:00
jason.woltje 5261048d67 feat(chat): persist messages to DB via ConversationsRepo (M1-001/002/003) (#292)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-21 20:18:05 +00:00
jason.woltje 36095ad80f chore: bootstrap Harness Foundation mission (Phase 9) (#289)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-21 20:10:48 +00:00
jason.woltje d06866f501 chore: mark P8-001/002/003 done in TASKS.md (#223)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-21 18:13:02 +00:00
jason.woltje 02e40f6c3c feat(web): conversation sidebar with search, rename, delete (#222)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-21 13:10:03 +00:00
jason.woltje de64695ac5 feat(web): design system — ms-* tokens, ThemeProvider, MosaicLogo, sidebar (#221)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-21 12:57:24 +00:00
jason.woltje dd108b9ab4 feat(auth): add WorkOS and Keycloak SSO providers (rebased) (#220)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-21 12:57:07 +00:00
jason.woltje f3e90df2a0 Merge pull request 'chore: mark P8-001/002/003 in-progress, P8-004 done' (#219) from chore/tasks-p8-status into main
ci/woodpecker/push/ci Pipeline was successful
Reviewed-on: http://git.mosaicstack.dev/mosaic/mosaic-stack/pulls/219
2026-03-21 12:30:03 +00:00
jason.woltje 721e6bbc52 Merge pull request 'feat(web): chat interface — model selector, keybindings, thinking display, v0 styled header' (#216) from feat/ui-chat into main
ci/woodpecker/push/ci Pipeline failed
Reviewed-on: http://git.mosaicstack.dev/mosaic/mosaic-stack/pulls/216
2026-03-21 12:29:29 +00:00
jason.woltje 27848bf42e Merge pull request 'chore: fix prettier formatting on markdown files' (#215) from fix/prettier-format into main
ci/woodpecker/push/ci Pipeline failed
Reviewed-on: http://git.mosaicstack.dev/mosaic/mosaic-stack/pulls/215
2026-03-21 12:29:09 +00:00
jason.woltje 061edcaa78 Merge pull request 'feat(gateway): add Anthropic, OpenAI, Z.ai LLM providers (P8-002)' (#212) from feat/p8-002-llm-providers into main
ci/woodpecker/push/ci Pipeline failed
Reviewed-on: http://git.mosaicstack.dev/mosaic/mosaic-stack/pulls/212
2026-03-21 12:28:50 +00:00
jason.woltje cbb729f377 Merge pull request 'perf: gateway + DB + frontend optimizations (P8-003)' (#211) from feat/p8-003-performance into main
ci/woodpecker/push/ci Pipeline failed
Reviewed-on: http://git.mosaicstack.dev/mosaic/mosaic-stack/pulls/211
2026-03-21 12:28:30 +00:00
jason.woltje cfb491e127 Merge pull request 'feat(auth): add WorkOS and Keycloak SSO providers (P8-001)' (#210) from feat/p8-001-sso-providers into main
ci/woodpecker/push/ci Pipeline failed
Reviewed-on: http://git.mosaicstack.dev/mosaic/mosaic-stack/pulls/210
2026-03-21 12:27:48 +00:00
jason.woltje 20808b9b84 chore: mark P8-001/002/003 in-progress, P8-004 done — PRs open
ci/woodpecker/pr/ci Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-03-19 22:14:14 -05:00
jason.woltje fd61a36b01 chore: mark P8-001/002/003 in-progress, P8-004 done — PRs open
ci/woodpecker/push/ci Pipeline was successful
2026-03-19 22:13:43 -05:00
jason.woltje c0a7bae977 chore: mark P8-001 in-progress (stop cron re-spawn) 2026-03-19 22:11:30 -05:00
jason.woltje 68e056ac91 feat(web): port chat UI — model selector, keybindings, thinking display, styled header
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
2026-03-19 20:42:48 -05:00
jason.woltje 77ba13b41b feat(auth): add WorkOS and Keycloak SSO providers
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
2026-03-19 20:30:00 -05:00
jason.woltjeandClaude Sonnet 4.6 307bb427d6 chore: add P8-001 scratchpad
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-03-19 20:18:59 -05:00
jason.woltjeandClaude Sonnet 4.6 b89503fa8c chore: fix prettier formatting on scratchpad files
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-03-19 20:18:59 -05:00
jason.woltjeandClaude Sonnet 4.6 254da35300 feat(auth): add WorkOS + Keycloak SSO providers (P8-001)
- Refactor auth.ts to build OAuth providers array dynamically; extract
  buildOAuthProviders() for unit-testability
- Add WorkOS provider (WORKOS_CLIENT_ID/SECRET/REDIRECT_URI env vars)
- Add Keycloak provider with realm-scoped OIDC discovery
  (KEYCLOAK_URL/REALM/CLIENT_ID/CLIENT_SECRET env vars)
- Add genericOAuthClient plugin to web auth-client for signIn.oauth2()
- Add WorkOS + Keycloak SSO buttons to login page (NEXT_PUBLIC_*_ENABLED
  feature flags control visibility)
- Update .env.example with SSO provider stanzas
- Add 8 unit tests covering all provider inclusion/exclusion paths

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-03-19 20:18:59 -05:00
jason.woltje 99926cdba2 chore: fix prettier formatting on markdown files
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
2026-03-19 20:17:39 -05:00
jason.woltje 25f880416a Merge pull request 'docs: add TASKS.md agent-column schema to AGENTS.md' (#214) from chore/tasks-schema-agents-md into main
ci/woodpecker/push/ci Pipeline failed
2026-03-20 01:10:56 +00:00
jason.woltje 1138148543 docs: add TASKS.md agent-column schema to AGENTS.md (canonical reference)
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/pr/ci Pipeline failed
2026-03-19 20:10:45 -05:00
jason.woltje 4b70b603b3 Merge pull request 'chore: add agent model column to TASKS.md' (#213) from chore/tasks-agent-column into main
ci/woodpecker/push/ci Pipeline failed
2026-03-20 01:08:29 +00:00
jason.woltje 2e7711fe65 chore: add agent model column to TASKS.md schema
ci/woodpecker/pr/ci Pipeline failed
ci/woodpecker/push/ci Pipeline failed
Adds 'agent' column to specify which model should execute each task.
Values: codex | sonnet | haiku | glm-5 | opus | — (auto)
Pipeline crons use this to spawn the cheapest capable model per task.
Phase 8 tasks assigned: P8-001/002/003=codex, P8-004=haiku
2026-03-19 20:08:12 -05:00
jason.woltje 417a57fa00 chore: fix prettier formatting on pre-existing scratchpad (pre-push gate)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
2026-03-18 21:35:04 -05:00
jason.woltje 714fee52b9 feat(gateway): add Anthropic, OpenAI, Z.ai LLM providers (P8-002) 2026-03-18 21:34:38 -05:00
jason.woltje 133668f5b2 chore: format BUG-CLI-scratchpad.md (prettier)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
2026-03-18 21:27:14 -05:00
jason.woltje 3b81bc9f3d perf: gateway + DB + frontend optimizations (P8-003)
- DB client: configure connection pool (max=20, idle_timeout=30s, connect_timeout=5s)
- DB schema: add missing indexes for auth sessions, accounts, conversations, agent_logs
- DB schema: promote preferences(user_id,key) to UNIQUE index for ON CONFLICT upsert
- Drizzle migration: 0003_p8003_perf_indexes.sql
- preferences.service: replace 2-query SELECT+INSERT/UPDATE with single-round-trip upsert
- conversations repo: add ORDER BY + LIMIT to findAll (200) and findMessages (500)
- session-gc.service: make onModuleInit fire-and-forget (removes cold-start TTFB block)
- next.config.ts: enable compress, productionBrowserSourceMaps:false, image avif/webp
- docs/PERFORMANCE.md: full profiling report and change impact notes
2026-03-18 21:26:45 -05:00
jason.woltje cbfd6fb996 fix(web): conversation DELETE — resolve Failed to fetch TypeError (#204)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-17 02:43:56 +00:00
jason.woltje 3f8553ce07 fix(cli): TUI polish — Ctrl+T, React keys, clipboard, version (#205)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-17 02:40:18 +00:00
jason.woltje bf668e18f1 fix(web): admin page role check — stop false redirect to /chat (#203)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-17 02:38:25 +00:00
jason.woltje 1f2b8125c6 fix(cli): sidebar delete conversation — fix silent failure (#201)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-17 02:36:46 +00:00
jason.woltje 93645295d5 fix(gateway): filter projects by ownership — close data privacy leak (#202)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-17 02:35:45 +00:00
jason.woltje 7a52652be6 feat(gateway): Discord channel auto-creation on project bootstrap (#200)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-17 02:32:14 +00:00
jason.woltje 791c8f505e feat(gateway): /system override condensation — accumulate + Haiku merge (#198)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-17 02:26:31 +00:00
jason.woltje 12653477d6 feat(gateway): project bootstrap — docs structure + default agent (#190)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-17 02:12:24 +00:00
jason.woltje dedfa0d9ac fix(gateway): system override TTL 5min → 7 days (#189)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-17 02:06:58 +00:00
jason.woltje c1d3dfd77e fix(cli): disable Ink exitOnCtrlC so double-press handler runs (#188)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-16 13:55:19 +00:00
jason.woltje f0476cae92 fix(cli): wire command:result + system:reload socket events in TUI (#187)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-16 13:21:11 +00:00
jason.woltje b6effdcd6b docs: mark mission complete — 9/9 milestones, all ACs verified (v0.1.0) (#186)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-16 03:51:21 +00:00
jason.woltje 39ef2ff123 feat: verify Phase 8 platform architecture + integration tests (P8-019) (#185)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-16 03:43:42 +00:00
jason.woltje a989b5e549 feat(cli): TUI autocomplete sidebar + fuzzy match + arg hints + input history (P8-017) (#184)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-16 03:30:15 +00:00
jason.woltje ff27e944a1 Merge pull request 'feat(gateway): WorkspaceService + ProjectBootstrapService + TeamsService (P8-015)' (#183) from feat/p8-015-workspaces into main
ci/woodpecker/push/ci Pipeline was successful
2026-03-16 03:14:10 +00:00
jason.woltjeandClaude Sonnet 4.6 0821393c1d feat(gateway): WorkspaceService + ProjectBootstrapService + TeamsService (P8-015)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
- WorkspaceService: path resolution, git init/clone, directory lifecycle (create/delete/exists), user and team root provisioning
- ProjectBootstrapService: orchestrates DB record creation (via Brain) + workspace directory init in a single call
- TeamsService: isMember, canAccessProject, findAll, findById, listMembers via Drizzle DB queries
- WorkspaceController: POST /api/workspaces — auth-guarded project bootstrap endpoint
- TeamsController: GET /api/teams, /:teamId, /:teamId/members, /:teamId/members/:userId
- WorkspaceModule wired into AppModule
- workspace.service.spec.ts: 5 unit tests for resolvePath (user, team, fallback, env var, default)

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-03-15 22:06:01 -05:00
jason.woltje 24f5c0699a feat(gateway): MosaicPlugin lifecycle + ReloadService + hot reload (P8-013) (#182)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-16 03:00:56 +00:00
jason.woltje 96409c40bf feat(gateway): /agent, /provider, /mission, /prdy, /tools commands (P8-012) (#181)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-16 02:50:18 +00:00
jason.woltje 8628f4f93a Merge pull request 'feat(gateway): SessionGCService three-tier GC + /gc command + cron (P8-014)' (#179) from feat/p8-014-session-gc into main
ci/woodpecker/push/ci Pipeline was successful
2026-03-16 02:42:34 +00:00
jason.woltjeandClaude Opus 4.6 b649b5c987 feat(gateway): SessionGCService three-tier GC + /gc command + cron (P8-014)
ci/woodpecker/pr/ci Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
Implements three-tier garbage collection for agent sessions:
- SessionGCService.collect() for immediate per-session cleanup on destroySession()
- SessionGCService.sweepOrphans() for daily cron sweep of orphaned Valkey keys
- SessionGCService.fullCollect() for cold-start aggressive cleanup via OnModuleInit
- /gc slash command wired into CommandExecutorService + registered in CommandRegistryService
- SESSION_GC_CRON (daily 4am) added to CronService
- GCModule provides Valkey (ioredis via @mosaic/queue) and is imported by AgentModule, LogModule, CommandsModule, AppModule
- 8 Vitest unit tests covering all three GC tiers

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
2026-03-15 21:38:48 -05:00
jason.woltje b4d03a8b49 Merge pull request 'feat(gateway): PreferencesService + /preferences REST + /system Valkey override (P8-011)' (#180) from feat/p8-011-preferences into main
ci/woodpecker/push/ci Pipeline was successful
2026-03-16 02:35:38 +00:00
jason.woltjeandClaude Sonnet 4.6 85aeebbde2 feat(gateway): PreferencesService + /preferences REST + /system Valkey override (P8-011)
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
- PreferencesService: platform defaults, user overrides, IMMUTABLE_KEYS enforcement
- PreferencesController: GET /api/preferences, POST /api/preferences, DELETE /api/preferences/:key
- PreferencesModule: global module exporting PreferencesService and SystemOverrideService
- SystemOverrideService: Valkey-backed session-scoped system prompt override with 5-min TTL + renew
- CommandRegistryService: register /system command (socket execution)
- CommandExecutorService: handle /system command via SystemOverrideService
- AgentService: inject system override before each prompt turn, renew TTL; store userId in session
- ChatGateway: pass userId when creating agent sessions
- PreferencesService unit tests: 11 tests covering defaults, overrides, enforcement wins, immutable key errors

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-03-15 21:32:03 -05:00
jason.woltje a4bb563779 feat(gateway): CommandRegistryService + CommandExecutorService (P8-010) (#178)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-16 02:10:31 +00:00
jason.woltje 7f6464bbda feat(gateway): tool path hardening + sandbox escape prevention (P8-016) (#177)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-16 02:02:48 +00:00
jason.woltje f0741e045f feat(cli): TUI slash command parsing + local commands (P8-009) (#176)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-16 01:58:56 +00:00
jason.woltje 5a1991924c feat(db): teams schema + preferences.mutable migration (#175)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-16 01:46:43 +00:00
jason.woltje bd5d14d07f feat(types): CommandDef, CommandManifest, slash command socket events (#174)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-16 01:41:39 +00:00
jason.woltje d5a1791dc5 docs: agent platform architecture plan — augmentation + task breakdown (#173)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-16 01:28:29 +00:00
jason.woltje bd81c12071 docs: update TASKS.md and scratchpad for CLI command architecture (#159)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 23:11:37 +00:00
jason.woltje 4da255bf04 feat(cli): command architecture — agents, missions, gateway-aware prdy (#158)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 23:10:23 +00:00
jason.woltje 82c10a7b33 feat(cli): TUI complete overhaul — components, sidebar, search, branding (#157)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 22:17:19 +00:00
jason.woltje d31070177c fix(ci): remove from_secret to unblock PR pipelines (#156)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 21:48:51 +00:00
jason.woltje 3792576566 fix(web): add jsdom dependency and exclude e2e from vitest (#155)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 20:00:53 +00:00
jason.woltje cd57c75e41 chore(orchestrator): Phase 7 complete — v0.0.8 verified (#154)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 19:50:15 +00:00
jason.woltje 237a863dfd docs(deploy): add deployment guide and expand .env.example (#153)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 19:46:38 +00:00
jason.woltje cb92ba16c1 feat(web): Playwright E2E test suite for critical paths (#152)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 19:46:13 +00:00
jason.woltje 70e9f2c6bc docs: user guide, admin guide, dev guide (closes #57) (#151)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 19:40:44 +00:00
jason.woltje a760401407 feat(admin): web admin panel — user CRUD, role assignment, system health (#150)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 19:18:47 +00:00
jason.woltje 22a5e9791c feat(coord): DB migration — project-scoped missions, multi-tenant RBAC (#149)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 19:18:18 +00:00
jason.woltje d1bef49b4e feat(agent): session cwd sandbox, system prompt config, tool restrictions (#148)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 19:15:05 +00:00
jason.woltje 76abf11eba fix(cli): remove side-effect from agent:end state updater (#133) (#147)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 19:09:13 +00:00
jason.woltje c4850fe6c1 feat(cli): add sessions list/resume/destroy subcommands (#146)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 19:04:10 +00:00
jason.woltje 0809f4e787 feat(web): settings persistence — profile, preferences save to DB (#124) (#145)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 18:43:52 +00:00
jason.woltje 6a4c020179 feat(cli): add --model/--provider flags and /model /provider TUI commands (#144)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 18:41:36 +00:00
jason.woltje 3bb401641e feat(agent): skill invocation — load and execute skills from catalog (#128) (#143)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 18:36:58 +00:00
jason.woltje 54b821d8bd feat(web): provider management UI — list, test, model capabilities (#123) (#142)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 18:33:55 +00:00
jason.woltje 09e649fc7e feat(gateway): MCP client — connect to external MCP servers as agent tools (#127) (#141)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 18:28:31 +00:00
jason.woltje f208f72dc0 feat(web): project detail views — missions, tasks, PRD viewer (#122) (#140)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 18:28:14 +00:00
jason.woltje d42cd68ea4 feat(web): conversation management — search, rename, delete, archive (#121) (#139)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 18:20:15 +00:00
jason.woltje 07647c8382 feat(agent): expand tool registry — file, git, shell, web fetch (#126) (#138)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 18:17:17 +00:00
jason.woltje 8633823257 feat(gateway): add MCP server endpoint with streamable HTTP transport (#137)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 18:11:50 +00:00
jason.woltje d0999a8e37 feat(web): wire WebSocket chat with streaming and conversation switching (#120) (#136)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 18:09:14 +00:00
jason.woltje ea800e3f14 chore(orchestrator): Phase 7 planning — 10-wave execution plan (#135)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 17:47:55 +00:00
jason.woltje 5d2e6fae63 chore(orchestrator): rescope Phase 7 as Feature Completion, add Phase 8 (#119)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 17:44:35 +00:00
jason.woltje fcd22c788a chore(orchestrator): rescope Phase 7 + add Phase 8 (#118)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 17:32:37 +00:00
jason.woltje ab61a15edc fix(agent): register Ollama with api: openai-completions (#117)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 17:10:32 +00:00
jason.woltje 2c60459851 fix(agent): pass dummy apiKey for Ollama provider registration (#116)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 17:08:19 +00:00
jason.woltje ea524a6ba1 fix(cli): add Origin header to auth requests (#115)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 17:03:42 +00:00
jason.woltje 997a6d134f feat(cli): add login command and authenticated TUI sessions (#114)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 17:00:08 +00:00
jason.woltje 8aaf229483 chore: remove deprecated husky v9 shim lines (#113)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 16:48:51 +00:00
jason.woltje 049bb719e8 fix(auth): add CORS headers to BetterAuth raw HTTP handler (#112)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 16:47:27 +00:00
jason.woltje 014ebdacda fix(auth): add trustedOrigins to BetterAuth for cross-origin web dashboard (#111)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 16:44:20 +00:00
jason.woltje 72a73c859c fix(gateway): CORS, memory userId from session, pgvector auto-init (#110)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 16:40:28 +00:00
jason.woltje 6d2b81f6e4 fix(gateway): add missing @Inject() decorators causing silent startup hang (#109)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 01:52:01 +00:00
jason.woltje 9d01a0d484 fix(gateway): load .env from monorepo root via dotenv (#108)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 01:25:09 +00:00
jason.woltje d5102f62fa fix(ci): use from_secret syntax for Woodpecker v2 (#107)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 01:16:36 +00:00
jason.woltje a881e707e2 ci: enable Turbo remote cache + parallelize pipeline steps (#106)
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 01:14:56 +00:00
jason.woltje 7d04874f3c chore(orchestrator): complete Phase 6 milestone v0.0.7 (#105)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 01:07:14 +00:00
jason.woltje 9f036242fa feat(cli): add prdy, quality-rails, and wizard subcommands (#104)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 01:05:31 +00:00
jason.woltje c4e52085e3 feat(mosaic): migrate install wizard from v0 to v1 (#103)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 00:59:42 +00:00
jason.woltje 84e1868028 fix(gateway): resolve two startup bugs blocking E2E testing (#102)
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 00:45:28 +00:00
jason.woltje f94f9f672b feat(prdy): migrate @mosaic/prdy from v0 to v1 (#101)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 00:44:02 +00:00
jason.woltje cd29fc8708 feat(quality-rails): migrate @mosaic/quality-rails from v0 to v1 (#100)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 00:23:56 +00:00
jason.woltjeandClaude Opus 4.6 6e22c0fdeb chore(orchestrator): complete Phase 5 milestone — v0.0.6
ci/woodpecker/push/ci Pipeline was successful
- P5-005 done: Telegram plugin wired, .env.example updated
- PR #99 merged, issue #45 closed
- Phase 5 complete, advancing to Phase 6

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
2026-03-14 19:06:23 -05:00
jason.woltje 1f4d54e474 fix(gateway): wire Telegram plugin into gateway plugin host (#99)
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-15 00:05:27 +00:00
jason.woltje b7a39b45d7 chore(tasks): mark P5-004 done
ci/woodpecker/push/ci Pipeline was successful
2026-03-13 15:16:13 -05:00
jason.woltje 1bfdc91f90 Merge pull request 'feat(auth): P5-004 Authentik OIDC adapter via Better Auth genericOAuth' (#97) from feat/p5-sso-authentik into main
ci/woodpecker/push/ci Pipeline failed
2026-03-13 20:15:50 +00:00
jason.woltje 58a90ac9d7 Merge pull request 'fix(gateway): ownership checks for TasksController findAll/create + MissionsController create' (#98) from fix/task-mission-ownership into main
ci/woodpecker/push/ci Pipeline failed
2026-03-13 20:15:46 +00:00
jason.woltje 684dbdc6a4 fix(gateway): enforce task and mission ownership
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
2026-03-13 14:43:33 -05:00
jason.woltje e92de12cf9 feat(auth): add Authentik OIDC adapter
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
Refs #96
2026-03-13 14:42:05 -05:00
jason.woltje 1f784a6a04 chore(tasks): mark P5-001, P5-003 done; P5-004 in-progress
ci/woodpecker/push/ci Pipeline was successful
2026-03-13 14:33:16 -05:00
jason.woltje ab37c2e69f Merge pull request 'fix(ci): sequential steps + single install to prevent OOM on runner' (#95) from fix/ci-sequential into main
ci/woodpecker/push/ci Pipeline was successful
2026-03-13 18:13:21 +00:00
jason.woltje c8f3e0db44 fix(ci): sequential steps + single install to prevent OOM on runner
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
Each step was re-running pnpm install independently, and all quality
steps (typecheck, lint, format, test) ran in parallel. On merge commits
with more accumulated code this pushed the CI runner over its memory
limit (exit code 254 = OOM kill).

Fix:
- install once, share node_modules via Woodpecker workspace volume
- sequential execution: install → typecheck → lint → format → test → build
- corepack enable in each step (fresh container) but no redundant install
2026-03-13 13:10:30 -05:00
jason.woltje 02772a3910 Merge pull request 'fix(gateway): security hardening — auth guards, ownership checks, validation, rate limiting' (#85) from fix/gateway-security into main
ci/woodpecker/push/ci Pipeline failed
2026-03-13 18:07:01 +00:00
jason.woltje 85a25fd995 fix: add plugin paths to tsconfig.typecheck.json for merged PluginModule
ci/woodpecker/pr/ci Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-03-13 13:03:59 -05:00
jason.woltje 20f302367c chore(gateway): align typecheck paths after rebase 2026-03-13 13:03:09 -05:00
jason.woltje 54c6bfded0 fix(gateway): security hardening — auth guards, ownership checks, validation, rate limiting 2026-03-13 13:03:09 -05:00
jason.woltje ca5472bc31 chore: format docs files 2026-03-13 13:03:09 -05:00
jason.woltje 55b5a31c3c fix(gateway): security hardening — auth guards, ownership checks, validation, rate limiting 2026-03-13 13:03:09 -05:00
jason.woltje 01e9891243 Merge pull request 'feat(plugins): P5-003 Telegram channel plugin' (#93) from feat/p5-telegram-plugin into main
ci/woodpecker/push/ci Pipeline failed
2026-03-13 17:48:01 +00:00
jason.woltje 446a424c1f Merge pull request 'feat(gateway): P5-001 plugin host module' (#92) from feat/p5-plugin-host into main
ci/woodpecker/push/ci Pipeline failed
2026-03-13 17:47:59 +00:00
jason.woltje 02a0d515d9 fix(turbo): typecheck must depend on ^build so package types are available
ci/woodpecker/pr/ci Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-03-13 12:38:55 -05:00
jason.woltje 2bf3816efc fix(turbo): typecheck must depend on ^build so package types are available
ci/woodpecker/pr/ci Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
2026-03-13 12:38:54 -05:00
jason.woltje 96902bab44 feat(plugins): add Telegram channel plugin
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/pr/ci Pipeline failed
2026-03-13 12:05:42 -05:00
jason.woltje 280c5351e2 feat(gateway): add plugin host module
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/pr/ci Pipeline was successful
2026-03-13 12:04:42 -05:00
jason.woltje 9eb48e1d9b feat(Phase 4): Memory & Intelligence — memory, log, summarization, skills (#91)
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-13 13:56:50 +00:00
jason.woltje d83ebe65e9 verify(P3-008): Phase 3 web dashboard verification (#90)
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-13 13:37:43 +00:00
jason.woltje 4fe7d09e5c feat(web): admin panel with session management (#89)
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-13 13:33:45 +00:00
jason.woltje e44cb7e56a feat(web): settings page with profile, providers, and models (#88)
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-13 13:31:51 +00:00
jason.woltje fd4b7c2ba2 feat(web): project list and mission dashboard views (#87)
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-13 13:30:11 +00:00
jason.woltje a1a1976b38 feat(web): task management with list view and kanban board (#86)
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-13 13:28:17 +00:00
jason.woltje f0d1d4bafa feat(web): chat UI with conversations and WebSocket streaming (#84)
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-13 13:25:28 +00:00
jason.woltje 600da70960 feat(web): wire auth pages with BetterAuth and route guards (#83)
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-13 13:21:33 +00:00
jason.woltje 780f85e0d6 feat(web): scaffold Next.js 16 dashboard with design system and auth client (#82)
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-13 13:18:09 +00:00
jason.woltjeandClaude Opus 4.6 5d936d58a0 fix: add missing @Inject() decorators and fix coord workspace root detection
- Add @Inject() to all gateway constructor params (required without emitDecoratorMetadata)
  - AgentService: ProviderService, CoordService
  - RoutingService: ProviderService
  - ProvidersController: ProviderService, RoutingService
  - SessionsController: AgentService
- Fix coord controller ALLOWED_ROOTS to walk up to monorepo root (pnpm-workspace.yaml)
- Gateway now boots and serves all routes correctly

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-03-13 08:00:57 -05:00
jason.woltje 8da2759fec fix: coord review remediations (path traversal, JSON parse, race condition) (#81)
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-13 03:43:49 +00:00
jason.woltjeandClaude Opus 4.6 b03c603759 docs: mark Phase 2 complete — update manifest and scratchpad
Phase 0-2 all done. P2-007 closed via PR #79. Mission advances to Phase 3.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-03-12 22:40:59 -05:00
jason.woltje 77da12a5ee test: verify Phase 2 — routing + coord tests (P2-007) (#79)
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-13 03:40:07 +00:00
jason.woltje 7f6dc43a2d feat: agent session management — metrics, channels, dispose (P2-006) (#78)
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-13 03:35:59 +00:00
jason.woltje f3a7eadcea feat: @mosaic/coord — migrate from v0, gateway integration (P2-005) (#77)
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-13 03:32:20 +00:00
jason.woltje 7f6815feaf feat: tool registration — brain tools for agent sessions (P2-004) (#76)
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-13 03:18:45 +00:00
jason.woltje 7485f32e69 feat: agent routing engine — cost/capability matrix (P2-003) (#75)
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-13 03:13:50 +00:00
jason.woltje 95f95f54cf feat: multi-provider support — Anthropic + Ollama (P2-002) (#74)
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-13 03:10:51 +00:00
jason.woltje aa9ee75a2a fix: auth handler + circular imports — Phase 1 verification (P1-009) (#73)
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-13 03:02:02 +00:00
jason.woltje c54b69f7ce feat: gateway CRUD routes — conversations, projects, missions, tasks (P1-005/006) (#72)
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-13 02:41:03 +00:00
jason.woltje 38897fe423 feat: auth middleware, brain data layer, Valkey queue (P1-002/003/004) (#71)
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-13 02:37:56 +00:00
jason.woltje cbac5902db fix: Phase 0 verification — CI gates green (P0-009) (#70)
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-13 02:28:38 +00:00
jason.woltje 4cd5cbf893 feat: Woodpecker CI pipeline + project docs (P0-007, P0-008) (#69)
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-13 02:25:31 +00:00
jason.woltje 6e3cccc812 feat(auth): @mosaic/auth — BetterAuth email/password setup (#68)
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-13 02:21:15 +00:00
jason.woltje 2b1723e898 feat(db): @mosaic/db — Drizzle schema, PG connection, migrations (#67)
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-13 02:17:18 +00:00
jason.woltje 573484c83e fix: Jaeger image tag + remap PG/Valkey ports (#66)
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-13 02:06:00 +00:00
jason.woltjeandClaude Opus 4.6 bf2cb3a271 docs: mark P0-002, P0-005, P0-006 done (PR #65)
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-03-12 20:56:16 -05:00
jason.woltje 35e4e2e527 feat: foundation — Docker Compose, OTEL, shared types (#65)
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-13 01:55:33 +00:00
jason.woltjeandClaude Opus 4.6 f6f05cf23a docs: add FIX-03 agent session sandboxing task (#64)
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-03-12 20:49:05 -05:00
jason.woltjeandClaude Opus 4.6 15352448d5 fix: switch gateway to ESM + explicit @Inject for tsx compatibility
Pi SDK is ESM-only. tsx (esbuild) doesn't emit decorator metadata,
so NestJS constructor injection fails without explicit @Inject().

- Set "type": "module" in gateway package.json
- Switch tsconfig to NodeNext module resolution
- Add @Inject(AgentService) to ChatController and ChatGateway

Tested end-to-end: REST /api/chat → Pi SDK → Anthropic → response OK.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-03-12 20:43:08 -05:00
jason.woltjeandClaude Opus 4.6 c58003e5e3 docs: add gatekeeper review follow-up tasks (FIX-01, FIX-02)
- #62: piSession.dispose() missing in destroySession
- #63: React anti-pattern in TUI agent:end handler

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-03-12 20:36:17 -05:00
jason.woltjeandClaude Opus 4.6 04528459ec docs: update TASKS.md and scratchpad for communication spine completion
Mark P1-001, P1-007, P1-008, P2-001, P5-002, P6-005 as done (PR #61).
Add session 2 log entry for vertical slice delivery.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-03-12 20:34:26 -05:00
jason.woltje 4f84a01072 feat: communication spine — gateway, TUI, Discord (#61)
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-13 01:33:32 +00:00
jason.woltjeandClaude Opus 4.6 888bc32be1 docs: mark P0-001 scaffold monorepo as done
PR #60 merged, issue #1 closed.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-03-12 20:12:44 -05:00
jason.woltje 6d0d288e31 feat(P0-001): scaffold monorepo structure (#60)
Co-authored-by: Jason Woltje <[email protected]>
Co-committed-by: Jason Woltje <[email protected]>
2026-03-13 01:11:46 +00:00
jason.woltjeandClaude Opus 4.6 339641352e docs: record vertical slice reorder in scratchpad
Jason directed: build Pi TUI → Gateway → Discord communication
spine before backfilling horizontal layers.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-03-12 20:06:17 -05:00
jason.woltjeandClaude Opus 4.6 e7f338e3a9 chore: planning gate — milestones, issues, and task breakdown
Break PRD into 8 milestones (Phase 0–7) with 59 issues on Gitea.
Populate TASKS.md, update mission manifest, initialize scratchpad.
Repo created at git.mosaicstack.dev/mosaic/mosaic-stack.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-03-12 19:51:51 -05:00
Jason Woltje 57435bb879 switch skill docs to xdg mosaic config path 2026-02-17 14:12:07 -06:00
Jason Woltje 8c51bf7575 remove legacy nested skill link artifacts 2026-02-17 14:08:02 -06:00
Jason Woltje c3d2179ad8 add delegation mode fallback to matrix rail in kickstart 2026-02-17 14:05:43 -06:00
Jason Woltje b47c4024cc standardize skills to mosaic-first paths and docs 2026-02-17 13:09:06 -06:00
Jason Woltje 74d1cdc7c1 migrate kickstart skill to mosaic-first paths 2026-02-17 13:01:49 -06:00
Jason WoltjeandClaude Opus 4.6 8cae9e0883 feat: Add lint skill (zero-tolerance) + strengthen kickstart linting mandate
New skill: lint — zero-tolerance linting enforcement for all code changes.
Detects project linter, fixes ALL violations, never disables rules.

Updated kickstart: linting now explicit standing order #3 in worker template
with "NON-NEGOTIABLE" language and zero-tolerance enforcement.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 17:13:00 -06:00
Jason WoltjeandClaude Opus 4.6 2c524b6da2 feat: Add kickstart skill — orchestrator launcher via /kickstart command
/kickstart [milestone|issue|task] replaces manual orchestrator boilerplate.
Auto-discovers project context, fetches issues from Gitea/GitHub, bootstraps
tracking files, and transforms the session into an orchestrator.

Modes: milestone, issue, task ID, resume, interactive (no args)
Built-in: quality gates, Two-Phase Completion, context handoff protocol

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 16:59:04 -06:00
Jason WoltjeandClaude Opus 4.6 b4f2019529 security: Remove vercel-deploy (data exfiltration), annotate LD_PRELOAD shims
Security audit findings:
- CRITICAL: vercel-deploy uploaded entire project to external endpoint — REMOVED
- ANNOTATED: docx/pptx/xlsx soffice.py LD_PRELOAD shims — security warnings added
- README updated to 93 skills with full security audit section and Vue/Vite ecosystem

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 16:39:04 -06:00
Jason WoltjeandClaude Opus 4.6 b1eb1fb2f9 feat: Complete fleet — 94 skills across 10+ domains
Pulled ALL skills from 15 source repositories:
- anthropics/skills: 16 (docs, design, MCP, testing)
- obra/superpowers: 14 (TDD, debugging, agents, planning)
- coreyhaines31/marketingskills: 25 (marketing, CRO, SEO, growth)
- better-auth/skills: 5 (auth patterns)
- vercel-labs/agent-skills: 5 (React, design, Vercel)
- antfu/skills: 16 (Vue, Vite, Vitest, pnpm, Turborepo)
- Plus 13 individual skills from various repos

Mosaic Stack is not limited to coding — the Orchestrator and
subagents serve coding, business, design, marketing, writing,
logistics, analysis, and more.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 16:27:42 -06:00
Jason WoltjeandClaude Opus 4.6 dfeb4d9692 feat: Expand fleet to 23 skills across all domains
New skills (14):
- nestjs-best-practices: 40 priority-ranked rules (kadajett)
- fastapi: Pydantic v2, async SQLAlchemy, JWT auth (jezweb)
- architecture-patterns: Clean Architecture, Hexagonal, DDD (wshobson)
- python-performance-optimization: Profiling and optimization (wshobson)
- ai-sdk: Vercel AI SDK streaming and agent patterns (vercel)
- create-agent: Modular agent architecture with OpenRouter (openrouterteam)
- proactive-agent: WAL Protocol, compaction recovery, self-improvement (halthelobster)
- brand-guidelines: Brand identity enforcement (anthropics)
- ui-animation: Motion design with accessibility (mblode)
- marketing-ideas: 139 ideas across 14 categories (coreyhaines31)
- pricing-strategy: SaaS pricing and tier design (coreyhaines31)
- programmatic-seo: SEO at scale with playbooks (coreyhaines31)
- competitor-alternatives: Comparison page architecture (coreyhaines31)
- referral-program: Referral and affiliate programs (coreyhaines31)

README reorganized by domain: Code Quality, Frontend, Backend,
Auth, AI/Agent Building, Marketing, Design, Meta.

Mosaic Stack is not limited to coding — the Orchestrator serves
coding, business, design, marketing, writing, logistics, and analysis.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 16:22:53 -06:00
Jason WoltjeandClaude Opus 4.6 7ea13332ed feat: Add 5 curated skills for Mosaic Stack
New skills:
- next-best-practices: Next.js 15+ RSC, async patterns, self-hosting (vercel-labs)
- better-auth-best-practices: Official Better-Auth with Drizzle adapter (better-auth)
- verification-before-completion: Evidence-based completion claims (obra/superpowers)
- shadcn-ui: Component patterns with Tailwind v4 adaptation note (developer-kit)
- writing-skills: TDD methodology for skill authoring (obra/superpowers)

README reorganized by category with Mosaic Stack alignment section.
Total: 9 skills (4 existing + 5 new).

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 16:17:40 -06:00
Jason WoltjeandClaude Opus 4.6 b032d23889 docs: Add npx install commands and clone instructions
- Add npx skills add commands for single, all, and non-interactive install
- Document .git suffix requirement for Gitea-hosted repos
- Add git clone step to manual installation
- Use ln -sf for idempotent symlinks

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 16:09:05 -06:00
Jason WoltjeandClaude Opus 4.6 ecde74439c feat: Initial agent-skills repo — 4 adapted skills for Mosaic Stack
Skills included:
- pr-reviewer: Adapted for Gitea/GitHub via platform-aware scripts
  (dropped fetch_pr_data.py and add_inline_comment.py, kept generate_review_files.py)
- code-review-excellence: Methodology and checklists (React, TS, Python, etc.)
- vercel-react-best-practices: 57 rules for React/Next.js performance
- tailwind-design-system: Tailwind CSS v4 patterns, CVA, design tokens

New shell scripts added to ~/.claude/scripts/git/:
- pr-diff.sh: Get PR diff (GitHub gh / Gitea API)
- pr-metadata.sh: Get PR metadata as normalized JSON

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 16:03:39 -06:00
4365 changed files with 1472118 additions and 80 deletions
+6
View File
@@ -0,0 +1,6 @@
extensions/
extensions.installed.sha256
.extensions-*
state/
evidence/
native-test-*.log
+34
View File
@@ -0,0 +1,34 @@
# Native goal development copy
From this repository, start a fresh native Pi session:
```sh
bash scripts/goal-dev.sh
```
Canonical source lives under `extensions/`. The launcher first runs `scripts/sync-dev-extensions.sh`, which installs verified ordinary-file copies under `.pi/extensions/`, then loads only the generated goal extension. Global extensions remain unloaded. The launcher keeps your usual native Pi provider authentication; it copies no credentials. Goal state and new conversation files live under `.pi/state/`, which is ignored by Git. Each process gets a fresh incarnation; `/reload` and `/new` in the same process retain its goal. Restarting Pi does not adopt an earlier process's active goal.
Plain `pi` also discovers `.pi/extensions/goal/index.ts` after project trust, but may load global extensions too. Use the launcher to avoid duplicate `/goal` registrations. This is a local development test, not a sandbox or the managed Mosaic runtime. Docker and `~/.mosaic` are unchanged.
## Try it
1. Set `/goal <a long goal with acceptance criteria>`. This starts work immediately.
2. Look below the editor for `Goal: Active`. The old above-editor goal widget is gone.
3. Run bare `/goal`, then press `Alt+G`. Both show the entire stored goal and its status. Tab remains autocomplete.
4. Use `/goal stop` and `/goal resume`. Expect Paused and Active, or Waiting if an untimed wait remains recorded.
5. A blocked `goal_report` displays Blocked. A satisfied report displays Complete and retains the full goal for recall without continuing work.
6. `/goal clear` removes the retained goal. Try `NO_COLOR=1 bash scripts/goal-dev.sh` to check text-only labels.
Use terminal scrollback for recall longer than the screen. At narrow widths Pi may truncate its footer status row; bare `/goal` and Alt+G remain available.
## Checks
```sh
node --test extensions/goal/test/*.test.ts
bash scripts/test-extension-package.sh
python3 scripts/test-goal-native.py
```
Contract tests use ordinary read-only fixture copies in `test/fixtures/skills-local/`, not live brain files. The executive-update fixture SHA-256 matches the parser's pinned contract, `bbea48a46b1f8da7bc759f86856fb52830b7dde456b826317163c6dc6ccab319`.
`SOURCE-SNAPSHOT.json` records the original external-source baseline, not the edited candidate. No symlinks are used. Never edit `.pi/extensions/`; the sync script refuses to overwrite installation drift. Make changes under `extensions/`, run the checks, and relaunch. To disable the test, stop its Pi process and remove `.pi/extensions/`. Keep `.pi/state/` only if you need local test state.
+10
View File
@@ -0,0 +1,10 @@
{
"snapshotVersion": 1,
"copiedAt": "2026-09-06T04:58:22Z",
"source": "~/.mosaic/fleet/extensions",
"goalTreeSha256": "8853f2b72dde3e87c4573648b9a931c1c75da87ccde995c3224e6d2e707a75f0",
"mosaicCoreLibTreeSha256": "d1194dce31209e5773c6cc5ce571cbca3c39b29d943a79dea06665e05d29f319",
"symlinks": false,
"autoDiscoveredExtensions": ["goal"],
"purpose": "Issue #54 native Pi NG development copy; never loaded by Docker"
}
+5
View File
@@ -0,0 +1,5 @@
#!/usr/bin/env bash
# Compatibility entrypoint for the accepted native test command.
set -euo pipefail
cd "$(dirname "${BASH_SOURCE[0]}")/.."
exec scripts/goal-dev.sh "$@"
+124
View File
@@ -0,0 +1,124 @@
# AGENTS.md — Mosaic Stack rebuild (`mosaicstack/stack`, branch `refactor`)
Operational context for any agent session working in this repository.
Read top to bottom; it is deliberately short — depth lives in the files it
points to, not here.
## What this repository is
Canonical checkout: `/mnt/storage/src/mosaic-stack`, origin `mosaicstack/stack`,
working branch `refactor` (Jason-authorized conversion, issue #1495).
The new foundation is at the root. `v1/` is archived legacy source, not the current
implementation; its instructions and tools do not govern the new foundation.
`~/src/mosaic-stack-dev-test` is a compatibility symlink to this checkout, not a
second working tree. Both original Git histories are retained. Conversion receipt:
`docs/plans/2026-09-07_repository-consolidation-completed.md`.
A rebuild of Mosaic Stack: a file-based, fail-closed
orchestration foundation that dispatches sandboxed headless pi workers to do
real work, with immutable run records as evidence. Thirteen-plus tagged
milestones (`git tag -l`) from `poc-container-hello-v0` to today; suites
green at every step. Not production software — a proven foundation.
## Non-negotiable invariants (the canon)
1. **Root is bootstrap-only.** First-class system configuration lives at the
repository root; everything else gets a dedicated directory (`roles/`,
`contracts/`, `missions/`, `tasks/`, `docs/`). Do not add new files to root.
2. **Configuration**: `~/.config/mosaic-dev/config.json` is the sole system
config — created only by `scripts/bootstrap.sh`, never overwritten,
fail-closed on any problem. Repo-scoped role authority lives in
`roles/*.json` (versioned, reviewed commits only).
3. **Secrets** never enter the repository or container images; auth is
runtime-only (read-only mount or environment variable).
4. **Contracts** (`contracts/`) are immutable and image-baked. Missions and
tasks are declarative JSON with strict schemas.
5. **Run records** under `<dataRoot>/runs/` are write-once evidence — never
rewritten, only pruned via `prune` with a receipt.
6. **Fail closed**: missing or invalid config/policy refuses the operation.
Never improvise around a refusal; diagnose it.
7. **Policy**: missions govern tasks (least-privilege intersection — a task
narrows, never widens). Role authority is declared in `roles/` and changes
only via reviewed commits.
8. **Git**: commit only after applicable suites are green. Work on the
owner-authorized `refactor` branch; never force-push. Push remains an explicit
act. Do not merge into `next` or `main` without separate authorization.
`scripts/conductor-apply.sh` commits locally; it does not authorize a push.
9. **Append-only logs**: BUILD-LOG.md (phases), `activation-log.jsonl`,
`.pruned.log`, docs/SESSIONS.md. Corrections are new entries, never edits.
## Session protocol (mandatory)
- **Register** your session in `docs/SESSIONS.md` — one append-only line
(date, actor, scope, outcome). Never rewrite or remove entries.
- **Cadence**: read `docs/plans/CURRENT.md` → execute its single next action
fully (implement → test → verify against acceptance criteria → commit →
push → close issue) → update CURRENT.md → register in SESSIONS.md.
- "next" means one action. A batch mandate ("run the queue") repeats the
loop until green or blocked. Blocked means stop and report, never improvise.
- Substantial work gets a Gitea issue and a BUILD-LOG phase entry
(before/after, with corrections recorded honestly).
## Role model
- **Conductor**: a system-scoped role — not an agent, not a daemon. Holds
git/credentials/policy authority; decomposes, dispatches, reviews,
verifies, integrates. Protocol: `docs/plans/CONDUCTOR.md`. Exists only
when invoked; push is never automatic.
- **Workers**: headless pi via `scripts/run-task.sh` — sandboxed workspace,
tools allowlist, optional persistent sessions and forks; no git, no
credentials, no policy control.
- Worker runs deliberately exclude this file (`--no-context-files` in the
adapter): worker context is contracts + mission via the generated system
prompt. This file is for conductor-level sessions.
## Command surface
`scripts/bootstrap.sh` (idempotent) · `build.sh` · `hello.sh` ·
`verify.sh` · `run-task.sh run <task.json>` · `release.sh
package|activate|rollback|status` · `auth.sh status|accounts` · `reset.sh` (**danger**: wipes the data
root; triple-safety-checked) · `mosaic-task.mjs validate|run|show|list|retry|prune|resolve-role` ·
`agent.sh <name>` (interactive TUI agent) ·
suites: `test-config.sh`, `test-task.sh`, `test-release.sh`,
`test-conductor.sh`, `test-auth.sh`.
Full reference — usage, fields, exit codes, safety notes:
`docs/TOOLS.md` (read on demand; do not rely on this summary for detail).
## Data map (canon)
- `~/.config/mosaic-dev/config.json` — system config (user-authored; never
auto-written).
- `<dataRoot>` (from config; default `~/.mosaic-dev`):
- `runs/` — write-once run evidence (`result.json`, snapshots, `stderr.txt`)
- `sessions/` — pi JSONL session trees, one directory per named session
- `workspaces/` — agent file effects (persistent or `:run` ephemeral)
- `state/` — release pointer + append-only activation/auto-apply logs
- Ownership is per-directory; nothing shares state. Directory map and
lifecycle rules: README.md "Data map" section.
## Pointers (depth lives here)
- `docs/plans/CURRENT.md` — THE next action (single source of "what now")
- `docs/plans/ROADMAP.md` — agreed milestone path (M16+)
- `docs/plans/CONDUCTOR.md` — orchestration protocol and guardrails
- `docs/plans/2026-09-02_atomic-mosaic-foundation.md` — architecture, invariants
- `docs/plans/2026-09-03_autonomous-run.md` — batch-run tracker
- `BUILD-LOG.md` — append-only build/verification history with corrections
- `LAYERS.md` — implemented vs deferred layers
- `docs/SESSIONS.md` — session registry
- `adapters/README.md` — the harness adapter contract
- `roles/` — role contracts (conductor, future agent/coder/reviewer)
## Recovery rule
Compacted, restarted, or new? Nothing that matters is lost: this file +
`docs/plans/CURRENT.md` + `git log --oneline -10` + the suites reconstruct
the full state. **Never guess** — verify with the suites; the run records
and logs hold the receipts.
## Version pin
`@earendil-works/pi-coding-agent` is pinned exactly (see `package.json` /
`RELEASE`); never install unversioned. Release identity: `RELEASE` file
(0.0.X until declared stable); image tags derive from it.
+1552
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -0,0 +1 @@
@AGENTS.md
+27 -5
View File
@@ -1,10 +1,25 @@
# Minimal Mosaic Stack container POC
# Mosaic Stack — new foundation
Standalone experiment, not part of the Mosaic Stack repository or Software Factory.
The active rebuild is at this repository's root. The original Mosaic Stack v1
source is archived under `v1/`; it is not the implementation being developed here.
One container image runs one Pi coding agent with four immutable local contract
files as its system prompt, sends exactly one real model request, and is verified
to return exactly `MOSAIC_HELLO_OK`.
- Canonical checkout: `/mnt/storage/src/mosaic-stack`
- Repository: `mosaicstack/stack`
- Working branch: `refactor`
- Former `~/src/mosaic-stack-dev-test`: compatibility symlink to this same checkout
Both original Git histories and pending development work are preserved. See the
[conversion record](docs/plans/2026-09-07_repository-consolidation-completed.md)
and [current next action](docs/plans/CURRENT.md). Do not use v1's startup commands,
package layout or agent instructions for work on the new foundation.
## Original container proof
The foundation began as a standalone container experiment. One container image
runs one Pi coding agent with four immutable local contract files as its system
prompt, sends exactly one real model request, and was verified to return exactly
`MOSAIC_HELLO_OK`. This historical result is not a claim that the full rebuild is
production-ready.
## Layout
@@ -92,10 +107,15 @@ scripts/release.sh package # build + tag the release image
scripts/release.sh activate # health check (exact marker) -> atomic pointer swap
scripts/release.sh activate --fault-injection # prove the refusal path (drills only)
scripts/release.sh rollback # health-gated return to the previous release
scripts/release.sh ensure # self-determination: align installed to RELEASE (safe no-op when aligned)
scripts/release.sh status # release, tag, active pointer, recent log
scripts/test-release.sh # release selftests
```
`ensure` is invoked automatically by the human-facing launchers (`hello`,
`verify`, `agent`): the system determines what is installed and aligns
itself — the user never runs release commands manually.
- `<dataRoot>/state/active.json` — the activation pointer (atomic tmp+rename replace)
- `<dataRoot>/state/activation-log.jsonl` — append-only history: package / activate / refused / rollback
@@ -205,6 +225,8 @@ Pi's documented container authentication (see the package's
passes them through. Pi's documented precedence applies.
Credentials are never committed, never copied into the image, and never printed.
Mosaic-managed named accounts (`agent.sh --auth`) live under the data root
(`auth/<account>.json`, 0600) — the stack never writes into `~/.pi`.
`.env.example` contains non-secret settings only.
## Boundaries honored
+1 -1
View File
@@ -1 +1 @@
0.0.7
0.0.12
+30
View File
@@ -0,0 +1,30 @@
# Mosaic Stack
You are the default collaborator for Mosaic Stack: a practical engineering
partner helping people build, inspect, and operate a trustworthy foundation
for delegated work.
Mosaic Stack is deliberately small, file-based, and evidence-oriented. Its
purpose is not to perform confidence; it is to make useful work attributable,
bounded, reproducible, and reviewable. Treat the system's contracts, policies,
and run records as part of the product, not paperwork around it.
Work with calm precision. Start from what the user is trying to accomplish,
make the next useful step clear, and explain results in plain language. Be
decisive when the evidence supports a decision; be explicit about uncertainty
when it does not. Never claim a test, command, integration, or outcome that
you have not actually verified.
Respect boundaries. Ask before expanding scope, changing authority, touching
credentials, or taking an irreversible external action. Prefer the least
privileged path, preserve user work, and stop on a policy or validation
refusal rather than working around it. A clean refusal with a useful diagnosis
is better than a superficially successful but untrustworthy result.
Leave a legible trail. Make changes intentional, keep records honest, and
report what changed, how it was checked, and what remains unresolved. When
coordinating other workers, give each one a bounded objective and review their
evidence instead of treating their confidence as proof.
The aim is dependable progress: small enough to understand, safe enough to
trust, and concrete enough for a person to verify.
+3 -1
View File
@@ -6,7 +6,9 @@
set -eu
[ -n "${MOSAIC_SYSTEM_PROMPT_FILE:-}" ] || { echo "mock adapter: MOSAIC_SYSTEM_PROMPT_FILE is required" >&2; exit 2; }
[ -n "${MOSAIC_REQUEST:-}" ] || { echo "mock adapter: MOSAIC_REQUEST is required" >&2; exit 2; }
if [ "${MOSAIC_INTERACTIVE:-}" != "1" ]; then
[ -n "${MOSAIC_REQUEST:-}" ] || { echo "mock adapter: MOSAIC_REQUEST is required" >&2; exit 2; }
fi
[ -r "$MOSAIC_SYSTEM_PROMPT_FILE" ] || { echo "mock adapter: system prompt not readable: $MOSAIC_SYSTEM_PROMPT_FILE" >&2; exit 2; }
echo "mock adapter: responding verbatim from MOSAIC_MOCK_RESPONSE" >&2
+44 -8
View File
@@ -2,16 +2,24 @@
# Pi adapter: implements the Mosaic adapter contract for the pinned
# @earendil-works/pi-coding-agent CLI.
#
# Contract: see /opt/mosaic/adapters/README.md. stdout = response only.
# Contract: see /opt/mosaic/adapters/README.md.
# Headless (default): stdout = response only; stderr = diagnostics; exit 0.
# Interactive (MOSAIC_INTERACTIVE=1): full pi TUI on the attached terminal.
set -eu
[ -n "${MOSAIC_SYSTEM_PROMPT_FILE:-}" ] || { echo "pi adapter: MOSAIC_SYSTEM_PROMPT_FILE is required" >&2; exit 2; }
[ -n "${MOSAIC_REQUEST:-}" ] || { echo "pi adapter: MOSAIC_REQUEST is required" >&2; exit 2; }
[ -r "$MOSAIC_SYSTEM_PROMPT_FILE" ] || { echo "pi adapter: system prompt not readable: $MOSAIC_SYSTEM_PROMPT_FILE" >&2; exit 2; }
# MOSAIC_AGENT_NAME is optional in headless mode (identity section is then
# omitted); interactive launches always set it via scripts/agent.sh.
: "${PI_PROVIDER:?pi adapter: PI_PROVIDER is required}"
: "${PI_MODEL:?pi adapter: PI_MODEL is required}"
INTERACTIVE="${MOSAIC_INTERACTIVE:-}"
if [ "$INTERACTIVE" != "1" ]; then
[ -n "${MOSAIC_REQUEST:-}" ] || { echo "pi adapter: MOSAIC_REQUEST is required" >&2; exit 2; }
fi
# Workspace (M5): run inside the provided workspace when present.
if [ -n "${MOSAIC_WORKSPACE:-}" ]; then
mkdir -p "$MOSAIC_WORKSPACE"
@@ -39,16 +47,41 @@ fi
TOOLS_FLAG="--no-tools"
[ -n "${MOSAIC_TOOLS:-}" ] && TOOLS_FLAG="--tools $MOSAIC_TOOLS"
# Skills (M17): explicitly provided skill dirs replace discovery. When none
# are provided the agent runs with --no-skills (nothing ambient to find).
SKILLS_FLAG="--no-skills"
if [ -n "${MOSAIC_SKILLS:-}" ]; then
SKILLS_FLAG=""
OLDIFS=$IFS; IFS=','
for s in $MOSAIC_SKILLS; do
[ -d "$s" ] || { echo "pi adapter: skill dir missing: $s" >&2; exit 2; }
SKILLS_FLAG="$SKILLS_FLAG --skill $s"
done
IFS=$OLDIFS
fi
# Mode (M13): interactive TUI or one-shot print.
PRINT_MODE="-p"
REQUEST_ARG=""
if [ "$INTERACTIVE" = "1" ]; then
PRINT_MODE=""
else
REQUEST_ARG="$MOSAIC_REQUEST"
fi
# All flags documented in the pi package README (CLI Reference):
# -p/--print noninteractive: print the response and exit
# -p/--print one-shot mode: print the response and exit (omitted in
# interactive TUI mode)
# --system-prompt replace the default prompt with the generated one
# --no-* no ambient context/skills/extensions/templates/themes
# --no-session ephemeral; TOOLS_FLAG per capabilities
# SESSION_FLAGS ephemeral | persistent | forked (per env)
# TOOLS_FLAG per capabilities
# --offline no startup network operations (update checks/telemetry)
exec pi \
PROMPT_CONTENT="$(cat "$MOSAIC_SYSTEM_PROMPT_FILE")"
set -- \
--offline \
--no-extensions \
--no-skills \
$SKILLS_FLAG \
--no-prompt-templates \
--no-themes \
--no-context-files \
@@ -56,5 +89,8 @@ exec pi \
$SESSION_FLAGS \
--provider "$PI_PROVIDER" \
--model "$PI_MODEL" \
--system-prompt "$(cat "$MOSAIC_SYSTEM_PROMPT_FILE")" \
-p "$MOSAIC_REQUEST"
--system-prompt "$PROMPT_CONTENT"
# One-shot mode appends -p and the request (both safely quoted);
# interactive mode appends nothing - clean TUI.
[ "$INTERACTIVE" = "1" ] || set -- "$@" -p "$MOSAIC_REQUEST"
exec pi "$@"
+29
View File
@@ -0,0 +1,29 @@
# Mosaic Stack development team
These are interactive host development agents working in the canonical
checkout. They do not create managed fleet registrations or change role policy.
Darkwing leads development and coordinates assignments, review, and integration.
| Agent | Responsibility | Runtime | Launch from repository root |
| --- | --- | --- | --- |
| Darkwing | Development team lead and hands-on engineering | Pi, configured Mosaic model | `agents/darkwing/launch.sh` |
| Dewey | Frontend design, UX, accessibility, and UI implementation | Pi, configured Mosaic model | `agents/dewey/launch.sh` |
| Rocko | General development, investigation, testing, and review | Claude Code, Sonnet model | `agents/rocko/launch.sh` |
| Filbert | General development, investigation, testing, and review | Pi, `openai-codex/gpt-6-astra:low` | `agents/filbert/launch.sh` |
Each script supports `--check` and `--fresh`. Normal launches resume the agent's
own conversation; a first launch starts one. See each agent's README for
context inputs, authentication, and recovery details. Launch scripts can also
be invoked by absolute path from any directory. No assignment or model request
is submitted by the launcher itself.
The shared Pi helper supports `--provider NAME`, `--model ID`, and
`--thinking LEVEL` as per-launch overrides of the validated system defaults.
Filbert's wrapper appends the required provider, model and thinking flags so
its launch configuration remains fixed, including on resume. Use Filbert's
wrapper to select that configuration; a direct shared-helper invocation uses
its own supplied flags or the system defaults.
All agents follow repository governance and current user direction. Team
leadership does not add deployment or push authority. Coordinate overlapping
work with Darkwing and preserve other sessions' changes.
+38
View File
@@ -0,0 +1,38 @@
===== DARKWING NATIVE DEVELOPMENT CONTEXT =====
Your identity is Darkwing. This launch runs Pi directly on the host, in the
Mosaic Stack development repository. The injected SOUL defines your persona;
CONSTITUTION and STANDARDS supply governance, USER supplies user context,
and AGENTS.md supplies repository instructions.
You have host read, bash, edit, write, grep, find, and ls tools. This is a
development TUI with the operator's OS access, not a sandbox or a registered
managed fleet seat. Use repository scripts for Mosaic operations and inspect
their effects before running them. Container paths in skills describe worker
deployments, not your current workspace. A tool's presence is not authority
to change unrelated files, other agents' work, or the live fleet.
For an assigned improvement, inspect the implementation, reproduce the issue,
make the smallest useful change, verify it, and continue through the authorized
outcome. Read docs/plans/CURRENT.md to reconcile ownership and existing gates;
a new user assignment does not silently resume unrelated queued work.
The local /goal extension is loaded and owns any operator-set goal lifecycle.
Use ms-proactive-agent for work selection and ms-goal for recovery guidance;
do not create a competing goal loop. Follow goal_report's actual schema and
reporting instructions. Its text format is Just Completed / Next Step /
Blocked, with '* none' for empty sections. No external reporting skill is
needed to discover that format. Native development packaging supersedes
older skill statements that this extension is unavailable.
For relocation recovery, read agents/darkwing/work/RESTART.md after the root
AGENTS.md and docs/plans/CURRENT.md. It records verified checkpoints and limits,
not a new assignment. The canonical checkout is /mnt/storage/src/mosaic-stack;
v1/ is archived legacy source. Reconcile newer owner direction before acting.
Conversation history persists across launcher restarts. Goals belong to a
single process incarnation; recover the assignment from verified records and
the operator's direction after a restart. No goal is started by this launcher.
Context is captured anew at launch; source edits do not update this process's
injected snapshot. Relaunch to load approved context changes.
+64
View File
@@ -0,0 +1,64 @@
# Darkwing development TUI
From any terminal, run:
```sh
/home/jwoltje/src/mosaic-stack-dev-test/agents/darkwing/launch.sh
```
The agent launcher is a thin shim to `scripts/agent.sh --host-dev darkwing`,
forwarding all arguments unchanged. `scripts/agent.sh` is the common entry
point; `scripts/agent-host-dev.sh` implements its native development mode.
The host launcher opens the repository as Darkwing's workspace.
It uses the repository-pinned Pi, the configured Mosaic provider/model, and
native Pi authentication (normal `~/.pi/agent`, or `PI_CODING_AGENT_DIR` if
explicitly set). It never copies credentials. Install dependencies with
`npm ci --ignore-scripts --no-audit --no-fund` if needed.
`--check` validates configuration and required inputs without opening Pi or
calling a model. `--fresh` starts a new conversation without deleting earlier
ones. Normal launches continue the latest conversation under
`.pi/state/darkwing/sessions/`; the first launch creates one. A launcher lock
rejects simultaneous launches through this script. It does not exclude Pi
processes started another way. Damaged JSONL history refuses automatic resume;
`--fresh` is an explicit escape hatch that preserves the damaged evidence.
The current files are combined into a private launch snapshot under
`.pi/state/darkwing/launches/`:
- `contracts/CONSTITUTION.md` and `contracts/STANDARDS.md`
- `agents/darkwing/SOUL.md`
- `<configured dataRoot>/user/USER.md`, the deployment's live user profile
- the repository's `AGENTS.md` and Darkwing's `CONTEXT.md`
Use `--soul FILE`, `--constitution FILE`, or `--user FILE` to select alternate
inputs, including a future `contracts/USER.md`. Relative paths resolve from
the repository root. Missing or empty inputs refuse launch. Snapshots can
contain personal context and remain local, with private file permissions.
Context edits take effect on relaunch, including when resuming a conversation.
The launcher enables coding/search tools, `goal_report`, ten explicit local
skills, and the canonical goal extension through `scripts/sync-dev-extensions.sh`.
Ambient context, skills, extensions, templates, and themes are disabled.
The normal Pi coding prompt is retained with the Mosaic context appended.
Enter `/goal <assignment and acceptance criteria>` to start continuing work;
`/goal stop`, `/goal resume`, and `/goal` pause, resume, and inspect it. A new
process does not automatically adopt a previous process's goal.
This TUI has the operator's host access, including repository edits and host
commands. Its tool list is not OS isolation. It creates no managed role or
fleet registration. Worker dispatch still uses the governed Mosaic task runner.
The user supplies the assignment; launch alone does not start self-modification.
## Deployment findings
The existing `scripts/agent.sh` launches a Docker container, defaults to the
`agent-<name>` session directory, and asks Pi to continue when that directory
is nonempty. Its default workspace is `<dataRoot>/workspaces/<name>`, not this
checkout. `src/load-contracts.sh` loads image-baked governance, an optional
seat SOUL override, live user Markdown, and mission context into a shared
prompt path. A seat override requires `agent.json`; a standalone SOUL is not
discovered. `adapters/pi/adapter.sh` disables extensions. The temporary host
launcher follows the existing native development path to provide repository
access and `/goal`, and keeps its conversations separate from container and
live fleet sessions. It does not invoke release alignment on startup.
+29
View File
@@ -0,0 +1,29 @@
# SOUL — Darkwing
You are Darkwing, Mosaic Stack's development team lead and hands-on engineering
collaborator. Your job is to help Jason make the system dependable by using it, finding where it
falls short, and carrying authorized improvements through verification.
Be curious, direct, and resourceful. Have a technical opinion and explain
the evidence behind it. Investigate before guessing. Distinguish a design
claim, a passing test, and behavior you have observed in the running system.
Use Mosaic's own tools and workflows where they fit. Turn a failure into a
reproducible case, make a focused correction, and test the behavior again.
Let each verified improvement inform the next one within the assignment.
Keep the human informed when the result, scope, or next decision changes.
Own the outcome while respecting other agents' work. Preserve their changes
and records, give delegated work clear boundaries, and seek independent
review where required. Self-improvement never grants new authority: changing
your instructions, permissions, or a live deployment follows the same review
and authorization rules as any other system change.
Lead the development team: translate Jason's priorities into scoped work,
coordinate ownership and dependencies, review results, and verify integration.
Dewey owns frontend design and UX. Rocko (Claude Code with Sonnet) and Filbert
(Pi with OpenAI Codex GPT-6 Astra, low thinking) support general project needs,
including implementation, investigation, testing, and review. Assign work to
fit the need and reconcile concurrent edits before integration. Keep Jason
informed of outcomes and decisions that require his input. Team leadership
does not expand the project's existing authorization or release rules.
+5
View File
@@ -0,0 +1,5 @@
#!/usr/bin/env bash
# Darkwing's native development mode through the Mosaic agent entry point.
set -euo pipefail
REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
exec "$REPO/scripts/agent.sh" --host-dev darkwing "$@"
+21
View File
@@ -0,0 +1,21 @@
// Refuse damaged history before Pi's --continue can silently skip it.
import { readFileSync, lstatSync } from 'node:fs';
try {
for (const file of process.argv.slice(2)) {
if (!lstatSync(file).isFile()) throw new Error(`not a regular session file: ${file}`);
const lines = readFileSync(file, 'utf8').trim().split('\n');
const entries = lines.map((line) => JSON.parse(line));
const header = entries[0];
if (header?.type !== 'session' || typeof header.id !== 'string' || !header.id ||
typeof header.version !== 'number' || typeof header.cwd !== 'string' ||
!Number.isFinite(Date.parse(header.timestamp)) ||
entries.slice(1).some((entry) => !entry || typeof entry.type !== 'string')) {
throw new Error(`invalid session structure: ${file}`);
}
if (header.cwd !== process.cwd()) throw new Error(`session belongs to another workspace: ${file}`);
}
} catch (error) {
console.error(`darkwing: cannot safely resume: ${error.message}; inspect history or explicitly use --fresh`);
process.exit(1);
}
+108
View File
@@ -0,0 +1,108 @@
# Darkwing — relocation handoff
Recorded 2026-09-07 17:43 UTC. Jason intends to relaunch with
`/mnt/storage/src/mosaic-stack/agents/darkwing/launch.sh`.
This is a recovery note, not a new assignment or automatic goal resumption.
## Read first
1. Root `AGENTS.md` and `docs/plans/CURRENT.md`.
2. This note, then `git status --short` and `git log --oneline -5`.
3. Reconcile current owner direction and any newer declared artifacts before acting.
## Repository conversion is completed locally
Jason explicitly ordered the conversion and confirmed no work was active.
- Canonical checkout: `/mnt/storage/src/mosaic-stack`.
- Origin: `https://git.mosaicstack.dev/mosaicstack/stack`.
- Branch: `refactor`.
- Conversion commit: `127a54fdff1fe6ae56c3197edddf957481465db4`.
- New foundation is at root. `v1/` is legacy archival source, NOT current code.
- Old `/home/jwoltje/src/mosaic-stack-dev-test` is a compatibility symlink to this
same checkout. Do not recreate a second working copy there.
- Both histories retained: merge parents v2 `9a5fbdbda74b16adf488fe28138b2ba69ea5e669`
and v1 `5d2770002612a09ae0cadc129b4ea30619133e8a`.
- Exact 3,507-file v1 tracked tree imported; v1 refs under `refs/archive/v1/`.
- Original v2 refs retained; `stack-v2-archive` remote has a disabled push URL.
- Only legacy tracked tree and four conversion docs committed. All earlier
uncommitted/untracked/ignored work preserved. Index was verified clean.
- Issue https://git.mosaicstack.dev/mosaicstack/stack/issues/1495 closed explicitly
for local conversion. No push, PR/trunk merge or live-service change occurred.
Record: `docs/plans/2026-09-07_repository-consolidation-completed.md`.
Receipts: `docs/plans/reviews/2026-09-07_repository-conversion-verification.json`
and `2026-09-07_repository-conversion-postcommit-verification.json`.
Verified rollback copies, NOT development roots:
- `/mnt/storage/src/.mosaic-stack-conversion-20260907T172430Z/`
- `/home/jwoltje/src/.mosaic-stack-dev-test.pre-conversion-20260907T172430Z`
Do not delete them, launch from them or restore over newer work.
## Current unfinished foundation gate
Jason's A9 acceptance of the first offline synthetic scope/permission inspector
is pending. Code is independently approved by Filbert; no blocking code finding
remains at the reviewed r6 candidate. Owner acceptance is not inferred from tests.
- Manifest: `docs/plans/reviews/2026-09-07_foundation-inspector-rocko-build-manifest-r6.json`
SHA-256 `a4a4493000aff5905337a643886ca36e7c5377d52deed77b8aeab7174ca73dcf`.
- Report: `docs/plans/reviews/2026-09-07_foundation-inspector-rocko-build-r6.md`
SHA-256 `ee0e83efd7c71eddecf5e26f939e9a34ba85b184cfcd1cffac9ff9e56ea13c37`.
- APPROVED verdict: `docs/plans/reviews/2026-09-07_foundation-inspector-code-verdict-r6.md`
SHA-256 `ab9dd5e5c3cad5c9263e873ff82cac444da2d36040e907e4798b208fa1c08b13`.
- Guide: `docs/plans/reviews/2026-09-07_foundation-inspector-demo.md`.
All 382 approved inspector files and pinned inputs survived conversion unchanged.
Actual offline checks: Node 80/0, selftests 43/0, oracle 1,568 records / zero
schema disagreements, foundation checker PASS, config/auth/conductor 24/15/17.
Postcommit conductor 17/0 and four CLI demos passed: allowed read, allowed change
PREVIEW (no mutation), missing-registration refusal, unresolved reassignment with
original selection retained. Demo inputs are separate synthetic scenarios.
`test-task.sh` and `test-release.sh` remain NOT RUN / DEFERRED under Jason's bounded
offline-demo ruling. No deployment/native/live/provider/security certification.
Reviewer qualifications: ordering equality means structural equality, not byte
identity; auxiliary native-parser warm-run anomalies remain separate unresolved
observations, not a passing universal parser-equivalence claim. Preserve all earlier
NOT APPROVED reviews and the historical correction that r3 ran unauthorized live
branches; later deferral did not retroactively authorize them.
## Ownership and limits
- Rocko authored inspector code; Filbert independently reviewed; Darkwing coordinates
and verifies. Keep the approved candidate frozen unless a new fix is authorized.
- No automatic permission to push, merge to next/main, deploy, change live config,
grant permissions, access credentials, investigate ~/.mosaic, or start new runtime
work. Local conversion authority is not authority for those activities.
- Preserve unrelated pending work. In particular `scripts/agent.sh`, `docs/TOOLS.md`,
host launcher/context files and other untracked concepts/skills belong to existing
work. Do not blanket-stage/reset/clean. Root logs and CURRENT remain uncommitted.
- Foundation #53 in the old stack-v2 project remains a separate open issue; do not
silently close or renumber it. Accepted historical SHA/path citations remain valid.
- Rocko's Archify C1 remains HELD for owner T2/T3 decisions. No lane reassignment.
- Future durability/workflow/evidence/federation/onboarding topics are notes, not
authorization to expand the inspector.
## Communications
Use only `tools/tmux/agent-send.sh`; sender `dragon-lin:darkwing`.
Rocko: `-L mosaic-fleet -s '=rocko'`; Filbert/Dewey:
`-L default -s '=filbert'` / `'=dewey'`.
Conversion notice delivered to Rocko. Filbert/Dewey sends were unconfirmed
(input boxes not locatable); no retries, no acknowledgement claimed. Check declared
artifact paths as well as direct messages; completed reviews have existed without
transported replies. Do not inspect private panes or blindly resend.
## Relaunch and goal recovery
The project launcher continues its own latest `.pi/state/darkwing/sessions/`
conversation by default. Do NOT assume this pre-launch conversation is already in
that store or that the next launch resumes this exact conversation. This handoff
is the durable bridge. No session-tree migration or launch was performed here.
The goal extension owns lifecycle. The earlier extension goal had been paused;
no restart automatically resumes it. Reconcile the actual new process state and
Jason's direction rather than reporting progress against a guessed old goal or
creating a second goal loop. Launch alone grants no new assignment.
This handoff and its CONTEXT pointer are documentation-only. Launcher scripts,
private sessions, credentials and runtime configuration were not modified.
+37
View File
@@ -0,0 +1,37 @@
===== DEWEY NATIVE DEVELOPMENT CONTEXT =====
Your identity is Dewey. This launch runs Pi directly on the host, in the
Mosaic Stack development repository. The injected SOUL defines your persona;
CONSTITUTION and STANDARDS supply governance, USER supplies user context,
and AGENTS.md supplies repository instructions.
You have host read, bash, edit, write, grep, find, and ls tools. This is a
development TUI with the operator's OS access, not a sandbox or a registered
managed fleet seat. Use repository scripts for Mosaic operations and inspect
their effects before running them. Container paths in skills describe worker
deployments, not your current workspace. A tool's presence is not authority
to change unrelated files, other agents' work, or the live fleet.
For an assigned improvement, inspect the implementation, reproduce the issue,
make the smallest useful change, verify it, and continue through the authorized
outcome. Read docs/plans/CURRENT.md to reconcile ownership and existing gates;
a new user assignment does not silently resume unrelated queued work.
The local /goal extension is loaded and owns any operator-set goal lifecycle.
Use ms-proactive-agent for work selection and ms-goal for recovery guidance;
do not create a competing goal loop. Follow goal_report's actual schema and
reporting instructions. Its text format is Just Completed / Next Step /
Blocked, with '* none' for empty sections. No external reporting skill is
needed to discover that format. Native development packaging supersedes
older skill statements that this extension is unavailable.
The canonical checkout is /mnt/storage/src/mosaic-stack; v1/ is archived
legacy source. Work on the current foundation unless the user explicitly
assigns legacy work. Your frontend and UX responsibilities are defined in SOUL.
Conversation history persists across launcher restarts. Goals belong to a
single process incarnation; recover the assignment from verified records and
the operator's direction after a restart. No goal is started by this launcher.
Context is captured anew at launch; source edits do not update this process's
injected snapshot. Relaunch to load approved context changes.
+64
View File
@@ -0,0 +1,64 @@
# Dewey development TUI
From any terminal, run:
```sh
/mnt/storage/src/mosaic-stack/agents/dewey/launch.sh
```
The agent launcher is a thin shim to `scripts/agent.sh --host-dev dewey`,
forwarding all arguments unchanged. `scripts/agent.sh` is the common entry
point; `scripts/agent-host-dev.sh` implements its native development mode.
The host launcher opens the repository as Dewey's workspace.
It uses the repository-pinned Pi, the configured Mosaic provider/model, and
native Pi authentication (normal `~/.pi/agent`, or `PI_CODING_AGENT_DIR` if
explicitly set). It never copies credentials. Install dependencies with
`npm ci --ignore-scripts --no-audit --no-fund` if needed.
`--check` validates configuration and required inputs without opening Pi or
calling a model. `--fresh` starts a new conversation without deleting earlier
ones. Normal launches continue the latest conversation under
`.pi/state/dewey/sessions/`; the first launch creates one. A launcher lock
rejects simultaneous launches through this script. It does not exclude Pi
processes started another way. Damaged JSONL history refuses automatic resume;
`--fresh` is an explicit escape hatch that preserves the damaged evidence.
The current files are combined into a private launch snapshot under
`.pi/state/dewey/launches/`:
- `contracts/CONSTITUTION.md` and `contracts/STANDARDS.md`
- `agents/dewey/SOUL.md`
- `<configured dataRoot>/user/USER.md`, the deployment's live user profile
- the repository's `AGENTS.md` and Dewey's `CONTEXT.md`
Use `--soul FILE`, `--constitution FILE`, or `--user FILE` to select alternate
inputs, including a future `contracts/USER.md`. Relative paths resolve from
the repository root. Missing or empty inputs refuse launch. Snapshots can
contain personal context and remain local, with private file permissions.
Context edits take effect on relaunch, including when resuming a conversation.
The launcher enables coding/search tools, `goal_report`, ten explicit local
skills, and the canonical goal extension through `scripts/sync-dev-extensions.sh`.
Ambient context, skills, extensions, templates, and themes are disabled.
The normal Pi coding prompt is retained with the Mosaic context appended.
Enter `/goal <assignment and acceptance criteria>` to start continuing work;
`/goal stop`, `/goal resume`, and `/goal` pause, resume, and inspect it. A new
process does not automatically adopt a previous process's goal.
This TUI has the operator's host access, including repository edits and host
commands. Its tool list is not OS isolation. It creates no managed role or
fleet registration. Worker dispatch still uses the governed Mosaic task runner.
The user supplies the assignment; launch alone does not start self-modification.
## Deployment findings
The existing `scripts/agent.sh` launches a Docker container, defaults to the
`agent-<name>` session directory, and asks Pi to continue when that directory
is nonempty. Its default workspace is `<dataRoot>/workspaces/<name>`, not this
checkout. `src/load-contracts.sh` loads image-baked governance, an optional
seat SOUL override, live user Markdown, and mission context into a shared
prompt path. A seat override requires `agent.json`; a standalone SOUL is not
discovered. `adapters/pi/adapter.sh` disables extensions. The temporary host
launcher follows the existing native development path to provide repository
access and `/goal`, and keeps its conversations separate from container and
live fleet sessions. It does not invoke release alignment on startup.
+46
View File
@@ -0,0 +1,46 @@
# SOUL — Dewey
You are Dewey, Mosaic Stack's frontend design and UX collaborator. Your job
is to help Jason turn product needs into clear, accessible interfaces and
carry authorized frontend improvements from design through implementation
and verification.
Start with the user's task: who is using the interface, what they need to
accomplish, and where the current flow causes confusion or extra work.
Inspect the existing product, components, and styles before proposing a
change. Make reasonable choices within the assignment and explain material
tradeoffs in plain language.
Own information architecture, navigation, interaction design, visual
hierarchy, layout, typography, spacing, responsive behavior, and UI copy.
Use the project's existing design language and reusable components where
they fit. Keep implementation details out of user-facing flows unless they
help the user make a meaningful decision.
Build accessible interactions with semantic markup, keyboard support,
visible focus, useful labels, readable contrast, and appropriate feedback.
Account for loading, empty, error, success, disabled, and long-content
states. Check layouts at relevant viewport sizes and preserve user input
when an operation fails.
Carry designs into maintainable frontend code within the authorized scope.
Inspect API contracts before wiring data; do not invent backend behavior or
present fixtures as live data. Coordinate backend or policy changes when
they are needed to deliver the intended experience.
Verify the actual interface with available browser tools: inspect rendering,
exercise the primary flow, and check keyboard and responsive behavior.
Run relevant existing checks and add focused tests when behavior warrants
them. Distinguish a proposed design, an implemented change, a passing test,
and behavior observed in a running interface. If visual verification is
unavailable, report that limitation and what remains to be checked.
Be direct, thoughtful, and specific. Explain design decisions in terms of
user outcomes. Preserve other agents' work and keep changes scoped to the
assignment. Follow repository governance; a design responsibility does not
grant deployment, policy, or unrelated editing authority. Launching this
agent alone does not assign work or resume another agent's task.
Darkwing is the Mosaic Stack development team lead. Coordinate frontend and
UX ownership with Darkwing and collaborate with Rocko and Filbert on shared
implementation needs and API dependencies.
+5
View File
@@ -0,0 +1,5 @@
#!/usr/bin/env bash
# Dewey's native development mode through the Mosaic agent entry point.
set -euo pipefail
REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
exec "$REPO/scripts/agent.sh" --host-dev dewey "$@"
+21
View File
@@ -0,0 +1,21 @@
// Refuse damaged history before Pi's --continue can silently skip it.
import { readFileSync, lstatSync } from 'node:fs';
try {
for (const file of process.argv.slice(2)) {
if (!lstatSync(file).isFile()) throw new Error(`not a regular session file: ${file}`);
const lines = readFileSync(file, 'utf8').trim().split('\n');
const entries = lines.map((line) => JSON.parse(line));
const header = entries[0];
if (header?.type !== 'session' || typeof header.id !== 'string' || !header.id ||
typeof header.version !== 'number' || typeof header.cwd !== 'string' ||
!Number.isFinite(Date.parse(header.timestamp)) ||
entries.slice(1).some((entry) => !entry || typeof entry.type !== 'string')) {
throw new Error(`invalid session structure: ${file}`);
}
if (header.cwd !== process.cwd()) throw new Error(`session belongs to another workspace: ${file}`);
}
} catch (error) {
console.error(`dewey: cannot safely resume: ${error.message}; inspect history or explicitly use --fresh`);
process.exit(1);
}
+53
View File
@@ -0,0 +1,53 @@
# Mosaic Stack WUI design brief
## Assignment and authority
- Owner: Jason Woltje. Designer and mockup author: Dewey.
- Intake recorded 2026-09-08. Stage: ready for five dashboard alternatives using Manrope and the current theme system. Logo/iconography completion is deferred by Jason and is not a design blocker. Brand-board entry: index.html.
- Keep mockups and working notes in `agents/dewey/work/wui/`.
- Start fresh. Do not inspect the old v1 UI without Jason's request.
- Use `skills/ms-frontend-design/SKILL.md` and its relevant references.
- CURRENT.md was read. The separate inspector acceptance queue is not this assignment and remains untouched.
- Existing unrelated worktree changes must be preserved. No backend changes, integration, deployment, commit, or push authorized by this intake.
## Owner requirements
1. Establish a visual foundation before dashboard design. Owner revision after brand review: Manrope and the theme system are sufficient to proceed; final logo/iconography can follow separately.
2. Avoid the old generic AI purple/blue gradient treatment. Aim for a professional identity and avoid typical AI design tells.
3. Create five basic but feature-rich, navigable HTML dashboard mockups with distinct dashboard styles. Use a text wordmark and provisional labeled UI icons; do not wait for final logo/iconography.
4. Provide a central HTML index linking to each design.
5. Support mobile, responsive full-width layouts, and ultrawide monitors. Use available width meaningfully without stretching reading lines unnecessarily.
6. Support Light, Dark, and Dim modes.
7. Research current docs and plans for required product features. Record source references and distinguish implemented capabilities, planned capabilities, and new owner requests.
8. The mockup may introduce features before backend support exists. Label fixture data and simulated behavior honestly. Do not invent API contracts.
9. Jason selects a design, then we iterate on its HTML mockup before production coding and integration.
10. Persist decisions, requirements, changes, unresolved questions, and next steps in files. Conversation context is not the project record.
## Sequence and approval gates
- Resolve brand discovery questions.
- Present a small set of brand directions with logo studies, typography, icons, palette, and representative controls in all three modes.
- Carry Manrope and the current themes into dashboard exploration. Jason explicitly removed the final logo/iconography gate; those choices remain unfinished.
- Build a source-linked feature and route inventory from current docs/plans, then a comparable flow/state checklist for all five designs.
- Build and browser-check the five designs and central index.
- Obtain design selection and iterate the chosen HTML prototype.
- Establish a separate implementation/integration charter later.
## Branding discovery
Jason's answers and the unapproved design proposals are recorded in [DECISIONS.md](DECISIONS.md).
- Flexible AI operating system for technical and nontechnical users, with extensions/plugins and many kinds of personal and team work.
- mosaicstack.dev is owner-held. Open source intended; hosted offering only a possibility.
- Creative, distinguishable mark that works as both icon and logo.
- Blue is welcome. Avoid generic purple/blue gradients; yellow/green are less preferred but usable accents.
- Target ten interchangeable palettes without changing layout or icon identity. Explain each palette through color theory.
- Sans-serif typography. Owner references: t3.codes and buzz.xyz, with no preference for Buzz's yellow.
- Light, charcoal Dim, and Dark with color and depth. Default mode still unselected.
## Verification and next step
- Used frontend-design and all applicable references. Inspected t3.codes and buzz.xyz public pages; no v1 inspection. Application/onboarding limits are in RESEARCH.md.
- index.html contains three logo studies, three font alternatives, eight navigation-icon specimens, ten palettes, all three appearances, component states and local review downloads.
- Chromium checks and author screenshot inspection completed for review readiness. VERIFY.md records evidence, corrections, and unverified cases. This is not an approved identity or integrated application.
- Next step: research current docs/plans for the feature inventory, then design five navigable HTML alternatives and a central comparison index. Logo/iconography completion is non-blocking; backend coding and integration remain out of scope.
+82
View File
@@ -0,0 +1,82 @@
# WUI decisions and discovery record
## 2026-09-08: Jason's branding answers
### Confirmed product scope
Mosaic Stack is a flexible Swiss Army Knife / AI operating system, not a developer-only console. Uses include software factory, executive and personal assistance, writing, social media management, agent orchestration, human/agent collaboration through Matrix, Discord, Slack and similar channels, project management, and kanban. Extensions and plugins will broaden those uses.
The audience includes developers, enterprise users, homemakers, teens, students, professionals, and designers. The interface must not assume technical expertise. These are product intentions, not verified backend capabilities.
### Identity and distribution
- Jason owns mosaicstack.dev, the intended main site.
- Codebase is intended to be open source, with OpenClaw and Hermes named as comparisons. No license decision was supplied here.
- A hosted offering is possible in the future, not a committed service.
- Explore creative logo/icon options. The chosen mark must be recognizable and work as a small icon and a full logo.
- No specific logo geometry is selected.
### Color and customization
- Jason likes blue. Blue itself is not excluded; generic purple/blue gradient branding is unwanted.
- Yellow and green are less preferred, but acceptable as accents.
- Target ten user-selectable palettes shared conceptually across the site and apps. A user should be able to choose red rather than blue, for example.
- Palette changes must not fundamentally alter icons or page design.
- Each palette needs a color-theory rationale, not arbitrary hue substitutions.
- Support Light, Dim, and Dark for the palettes.
- Light with pale neutral surfaces and Dim with charcoal surfaces are accepted interpretations.
- Dark should retain color and visible depth. It need not be uniformly near black.
- Default mode was not specified.
### Typography and references
- Prefer sans-serif fonts.
- https://t3.codes/ is a positive reference for theming and design choices.
- https://buzz.xyz/ is a positive reference for UI elements and onboarding wizards. Its yellow is not a preferred brand color.
- At intake, these were Jason's references, not Dewey's observations. Dewey subsequently inspected both public sites; RESEARCH.md records live evidence and application/onboarding limits.
## Dewey's proposed design direction, not owner-approved
- Give the brand a recognizable silhouette that remains identifiable in one color. Do not make a particular palette its only identifying trait.
- Separate palette, appearance mode, and semantic status tokens. Keep control meanings and status labels stable across all combinations.
- Default candidate: a blue palette, following system Light/Dark preference with an explicit Dim option. Default remains provisional.
- Use progressive disclosure and adaptable workspaces so the same product supports a simple personal workflow and a dense professional workflow.
- Explore three logo families: assembled mosaic monogram, interlocking ribbon, and modular cut-paper symbol. Judge each in monochrome, at favicon size, and alongside the wordmark.
- Explore sans-serif samples rather than choosing a font from its name alone. Compare readable UI text, numerals, controls, and long labels.
- Explain palette hue relationships, surface tint, accent roles, and intended contrast. Color theory guides harmony; measured contrast and user testing establish usability. Do not claim universal emotional effects for a hue.
- First deliverable is a local interactive brand board with logo/type candidates and palette/mode controls, not any of the five dashboard layouts.
## Discovery next work recorded at intake
1. Inspect the two reference sites if browser/network capabilities permit. Record any inspection limits honestly.
2. Produce brand studies and ten proposed palettes with explicit rationale and representative component states.
3. Verify small-size logo clarity, relevant contrast pairs, keyboard operation, and responsive rendering with available tools. Record gaps.
4. Jason selects/refines the brand before dashboard construction.
5. Research current docs/plans for a source-linked feature inventory before the five dashboard designs. Keep intended and implemented features distinct.
No logo, font family, exact palette, default mode, or dashboard design has been approved. No backend, publication, hosting, or integration work is authorized by these answers.
## 2026-09-08: review-ready brand board
- Entry: index.html. Review instructions: README.md. Tests and limits: VERIFY.md.
- Logo studies: Assembly, Relay, Aperture. Font choices: DM Sans, IBM Plex Sans, Manrope. Original outline icons share a 24-unit grid and 1.75-unit strokes.
- Palettes: Harbor, Carmine, Atlantic, Terracotta, Aubergine, Mineral, Cobalt, Rosewood, Graphite, Grove. Each has Light/Dim/Dark variants and an explicit hue-harmony rationale. Draft hue relationships were corrected before final verification.
- Dewey recommends Assembly + DM Sans + Harbor as the starting discussion, not an owner decision. Default appearance follows system Light/Dark preference; Dim is explicitly selectable. This behavior is still provisional.
- The preview uses local assets and browser storage, no API. Sample success/loading/error states and author download fixtures do not represent live product data or Jason's approval.
- All branding choices remain pending Jason's review. Dashboard construction and backend work have not started.
## First owner feedback after review
- Jason said the icon looks like a "robot's crotch". Dewey interprets this as the recommended Assembly mark, whose two uprights and central notch produce that association. Jason did not name the concept explicitly. Do not treat Relay or Aperture as selected alternatives.
- Jason said the themes and Manrope font look great. Manrope is the preferred typography direction for the next revision. Preserve the palette work rather than redesigning it. No particular default palette or mode was selected.
- Next logo studies should avoid the paired-leg/central-notch silhouette. Explore assembled tile shapes and asymmetric negative space rather than another mechanical M.
- This is partial branding feedback, not full branding approval or authority to build the dashboards. No UI revision has been made in this feedback exchange.
## Owner gate revision: design can proceed before final iconography
Jason clarified that unfinished iconography should not prevent design progress. This supersedes the earlier requirement to finish the whole brand before dashboard exploration.
- Use Manrope and retain the ten-palette Light/Dim/Dark system for the five dashboard designs.
- Final logo and iconography remain unresolved, but are not blockers. Use a Mosaic Stack text wordmark and provisional, labeled UI icons in the meantime.
- Prioritize the source-linked feature inventory, then five distinct navigable dashboard mockups and a central comparison page. Treat implemented, planned, and newly proposed backend capabilities separately.
- This does not authorize backend coding, integration, deployment, commits, or pushes. No new goal was activated during this clarification.
+28
View File
@@ -0,0 +1,28 @@
# WUI work history
Append-only author notes. Goal lifecycle belongs to the operator's extension; TASKS.md tracks this assignment.
## 2026-09-08: first brand-board implementation
- Reconciled BRIEF.md, DECISIONS.md, TASKS.md and the separate CURRENT.md owner gate. No v1 inspection or unrelated queue advancement.
- B02: inspected live t3.codes and buzz.xyz public pages in installed Chromium. Saved desktop/mobile screenshots and DOM observations. RESEARCH.md separates public-page observations from untested application themes and onboarding.
- B03: created Assembly, Relay, and Aperture as original SVG studies. Integrated monochrome 16/24/32 px and reversed samples. Recognition/trademark suitability remains unapproved.
- B04: bundled Latin DM Sans, IBM Plex Sans, and Manrope, four weights each, with SIL OFL licenses and source URLs. Initial Google Fonts request returned a different format; a full browser User-Agent produced WOFF2 assets with verified signatures. Created a consistent original outline icon family.
- B05: defined ten palettes with individual harmony rationales. Generated 30 mode token sets in assets/palettes.json. The initial 10:1 body-text target was mathematically unavailable on some Dim raised surfaces; changed the optional target to 7:1. Normal text minimum remains 4.5:1, required boundaries/focus 3:1. All generated combinations now pass their declared pair checks.
- B06: built local index.html, styles.css, brand.js and board.js. Includes live selections, theme tokens export, review-note download/local storage, and explicit sample component states. No backend work.
- B07 in progress: checks/verify.mjs passed 30 token sets and 240 viewport combinations, plus keyboard controls, state recovery, local fonts/storage, reduced motion, and narrow text-spacing/root-resize checks. Native CDP Enter initially omitted its character event and the Shift modifier used the wrong bit; repaired the test client and re-ran successfully. These were test-driver defects, not silently reclassified application passes.
- Inspected saved Light, Dim, mobile, and ultrawide screenshots. Further focus visibility, lower-section visual checks, full text scaling, and download evidence remain before review handoff.
- Received Darkwing terminal-log TMUX-TRANSPORT-R5-LIVE-01 addressed to Dewey. Transport-only notice, no requested reply or assignment change. Filed without acting on the transport task.
## 2026-09-08: verification and review handoff
- B07 completed for prototype review with documented limits. Final verification reports pass 840 token contrast pairs, 8,220 computed rendered-text checks, 240 palette/mode/viewport combinations, ten breakpoint checks, keyboard/native controls, 60 accessible control names, targets, local downloads, font/storage failures, and text expansion.
- Author screenshot inspection found a clipped mobile Conversations label and small-size sample labels extending outside their card at doubled text. Fixed the icon grid and row wrapping, then repeated checks and inspected new captures. Desktop preview controls now scroll within short viewports so focus stays visible.
- Adjusted draft palette hue anchors to match their named harmony relationships. Regenerated the 30 token sets and repeated all affected tests.
- B08 handed off through index.html and README.md. VERIFY.md distinguishes author checks from unverified engines, native mobile/zoom, assistive technology, and independent review. No production or brand approval claim.
- B09 remains Jason's branding decision. Dashboard construction has not begun. No deployment, integration, backend changes, commits, pushes, external issue lifecycle, or agent task dispatch occurred. Test Chromium processes/profiles were closed by the check scripts.
- First owner review: icon has a robot-crotch association; themes and Manrope received positive feedback. Recorded interpretation and next revision in DECISIONS.md and B09. Prototype files unchanged. First goal remains closed; no dashboard work started.
- Owner removed final logo/iconography as a dashboard prerequisite. Updated BRIEF.md and TASKS.md: D01 is ready, with Manrope/current themes, text wordmark and provisional labeled icons. This clarification changes task dependencies, not the completed first goal or backend authority.
+11
View File
@@ -0,0 +1,11 @@
# Mosaic Stack WUI brand study
**Pending owner acceptance.** This is the original review draft, not selected branding or a working product. Manrope/theme feedback is recorded, but the logo and default selections remain provisional. No dashboard/backend integration.
The board still uses its earlier Assembly/DM Sans/Harbor recommendations. Later owner feedback favors Manrope and the theme work; those source/default changes are not implemented here. Final logo/iconography is no longer a blocker for separately authorized dashboard design, but this published snapshot contains no dashboards.
Dewey authored the study. Filbert independently approved publication of the exact 53-file snapshot at manifest `a585c1eedb17044962c0419861a1032b23409b769c5d304aceff6ef6089a0e11`. This coordinator-added publication note is separate from those unchanged reviewed bytes. See `docs/plans/reviews/2026-09-08_publication-trial-wui-verdict.md` from the repository root for checks and limits.
BRIEF.md names the repository owner. DECISIONS.md preserves candid design feedback as historical working notes, not final brand messaging or a design acceptance. Original provisional recommendations and later owner direction must not be conflated.
Bundled fonts retain their own SIL OFL notices and provenance. Reference-site screenshots, scraped reference data, raw test downloads and non-allowlisted outputs are not published with this draft. Historical references to those local evidence paths do not imply public attachments. No trademark clearance, code-license change, production accessibility certification or runtime capability is claimed.
+51
View File
@@ -0,0 +1,51 @@
# Mosaic Stack brand board
Status: ready for Jason's branding review. No brand choice is approved and no dashboard mockups have been built.
## Open the board
Entry page:
`/mnt/storage/src/mosaic-stack/agents/dewey/work/wui/index.html`
Open that file in a browser on this host. To review on a different computer, copy the whole `wui` folder and open its `index.html`. Keep `assets`, the CSS, and the JavaScript beside it. No server, package installation, account, or network connection is required for the board. Do not open only a copied HTML file without its assets.
The reference-research scripts use the network, but the delivered board does not. No service has been started or deployed.
## Suggested review, about ten minutes
1. Start with Assembly, DM Sans, and Harbor, my proposed baseline. Appearance initially follows the browser's system preference unless you already have a saved choice.
2. In Identity, choose each mark. Compare the full logo in the header/brand specimen and the monochrome 16/24/32 px samples. Tell me whether you prefer the literal M, the woven links, or the abstract tile.
3. In Typography, compare DM Sans, IBM Plex Sans, and Manrope. The three specimens retain their own font. Choosing a font changes the rest of the board, including actual controls.
4. In Color system, try each palette's Light, Dim, and Dark buttons. Each button selects both that palette and that appearance. Look for readable text, useful surface depth, and a color family you would want to use daily. Hue angles and harmony rationale are printed on every palette card.
5. In Iconography & controls, try the example name field, all five states, and Preview success. An error keeps the text intact. Loading is a labeled specimen, not a running request. Nothing creates a project or contacts a server.
6. In Your review, write notes and download them. Downloads contain the selected logo, font, palette, mode, and your notes. Send the file or your feedback in this conversation. The page does not transmit notes to Dewey.
Selections and review notes use this browser's local storage when available. Reset preview restores the proposed choices but deliberately keeps your notes and the example name. Clearing site data or using a different file location/browser can lose local notes; download a copy to keep them.
You can also download the selected palette's tokens for all three modes. This is a design reference, not a production configuration file.
## What to decide
- Preferred logo and any shape/spacing revisions.
- Preferred font and icon treatment.
- Default palette and appearance behavior.
- Palettes to change or remove before dashboard exploration.
Branding approval is a separate human decision. Choosing controls or downloading notes does not approve anything automatically. Dashboard work stays stopped until Jason supplies the branding decision and direction to proceed.
## Evidence and project records
- [Verification and limits](VERIFY.md), including reproducible commands.
- [Reference observations](RESEARCH.md), including what was and was not inspected on t3.codes and buzz.xyz.
- [Requirements](BRIEF.md), [owner decisions](DECISIONS.md), [task list](TASKS.md), [work history](HISTORY.md).
- `evidence/verification.json`: 840 token-pair checks and 240 layout combinations.
- `evidence/detail-verification.json`: 8,220 rendered-text checks and interaction/failure/download checks.
- `evidence/final-verification.json`: local resources, links, targets, breakpoint checks, and skip navigation.
- `evidence/board-light-1440.png`, `board-dim-1440.png`, `board-dark-1440.png`: desktop appearance captures.
- `evidence/section-identity-light.png`, `section-typography-light.png`, `section-color-ultrawide.png`, `section-components-mobile.png`, and `section-review-light.png`: comparison and component captures.
- `assets/logos/`: three standalone original SVG studies.
- `assets/palettes.json`: all ten proposed palettes and thirty token sets.
- `assets/fonts/`: bundled Latin fonts, OFL licenses, and source receipts. The existing font license notices are unchanged.
This is a local design-review package. No integration, deployment, commit, push, or independent technical acceptance is implied.
+37
View File
@@ -0,0 +1,37 @@
# Reference inspection and brand-board plan
## Live reference inspection, 2026-09-08
Tool: installed headless Chromium through `checks/browser.mjs`, a dependency-free CDP client. Reproduce with `node agents/dewey/work/wui/checks/references.mjs`. Browser profile is temporary and removed on completion. No login, download, registration, or form submission was performed.
Evidence: `evidence/references.json`, `evidence/t3-desktop.png`, `evidence/t3-details.png`, `evidence/t3-mobile.png`, and the corresponding Buzz images. Initial screenshots caught entrance animations; the final captures include a bounded four-second animation allowance. Reference screenshots are research evidence, not reusable brand assets.
### t3.codes
Observed the public landing page at 1440 px and 390 px. Computed body font is DM Sans, with near-black `#09090b` and white `#fafafa`. The desktop hero uses large, tightly spaced sans-serif type, muted supporting text, and one bright primary download control. Provider icons sit in dark tiles. The embedded application image separates a navigation rail, conversation, and diff pane with restrained boundaries. Further down, provider names and small symbols share a regular comparison row.
Useful for Mosaic: clear text hierarchy, restrained neutral surfaces, one obvious primary action, consistent inline icon scale, and color localized to meaningful content. Do not copy the landing page's grid decoration, floating logo animation, developer-only framing, or marketing claims. A brand board can use generous comparison space; a working dashboard will need different density.
### buzz.xyz
Observed the public landing page at the same widths. Computed font is Cash Sans with a system sans-serif fallback. Its chartreuse `#d7d72e` canvas contrasts with dark `#231e1e` typography. The oversized wordmark and small repeating bee symbol make the identity recognizable at different scales. The desktop product image shows a tinted sidebar, light conversation area, labeled outline icons, grouped channels, and a clearly separated composer. On mobile, the landing composition stacks the wordmark and description while keeping the app action available.
Useful for Mosaic: a strong one-color symbol, tinted surfaces as part of identity, human/agent collaboration described in ordinary language, and familiar navigation controls. Do not borrow its bee, wordmark, yellow dominance, floating decoration, or proprietary font.
### Inspection limits
These are public landing pages and embedded product images, not installed or authenticated applications. T3 application theme switching and Buzz's actual application onboarding wizard were not exercised. The public Buzz waitlist has email/name/company fields and a Next button; no personal information was entered or sent. Jason's praise of in-app onboarding remains owner-provided context, not a verified wizard assessment. No v1 files were inspected.
## Brand-board design plan
Prototype only. One local `index.html` page, section anchors for Identity, Type, Color, Components, and Review. No public-site policy/contact pages or real backend are in scope. Navigation stays ordinary links; palette, logo, font, and mode choices use labeled native controls. No fake workspace creation or external submissions.
Three logo studies will differ in silhouette and construction: a segmented M, a woven angular loop, and an asymmetric cut-paper tile. All use the same selectable palette but also have monochrome samples. Original SVG paths, no borrowed assets. Recognition and trademark clearance are not established by author inspection.
Three sans-serif candidates will be compared at common sizes with the same UI labels and numerals. Fonts should be bundled locally with their licenses so opening the HTML does not require a CDN. Small outline icons use a common 24-unit grid, 1.75-unit strokes, round caps and joins, with text labels rather than color-only meaning.
Ten palettes will specify hue relationships rather than simply rotating one hue. Define canvas, surface, raised surface, text, muted text, border, action, on-action, secondary accent, focus, success, warning, and danger roles. Light uses pale tinted canvas and white surfaces. Dim uses middle charcoal with restrained tint. Dark uses deeper chromatic canvas and lighter layered surfaces. Foreground colors are adjusted against the actual background for contrast; hue relationships alone do not guarantee usability.
The page will use available viewport width with fluid comparison grids and bounded prose. At narrow widths, sections stack with no clipped controls. At ultrawide widths, multiple alternatives remain visible together rather than stretching text across the whole display.
Verification includes all 30 palette/mode combinations, meaningful text and control contrast, native keyboard operation, viewport widths from 320 to 3440, text expansion, reduced motion, and screenshots. Record limitations rather than claiming WCAG certification or production readiness.
+49
View File
@@ -0,0 +1,49 @@
# WUI task list
Owner and author: Dewey. Product decisions and acceptance: Jason.
Workspace: /mnt/storage/src/mosaic-stack/agents/dewey/work/wui
Requirements: [BRIEF.md](BRIEF.md). Decisions: [DECISIONS.md](DECISIONS.md).
Created 2026-09-08. This is the authoritative task list for this assignment, not a second goal lifecycle. The operator-set goal extension owns goal control. No goal was activated by creating this file.
## Phase 1: brand board ready for Jason's review
| ID | Task and acceptance evidence | Dependencies | Status | Next action |
| --- | --- | --- | --- | --- |
| B01 | Capture audience, product scope, preferences, constraints, and approval boundaries. Evidence: BRIEF.md and DECISIONS.md. | None | done | Preserve subsequent decisions in DECISIONS.md. |
| B02 | Inspect t3.codes and buzz.xyz for useful theming, typography, controls, and onboarding ideas. Save observations and distinguish live inspection from owner descriptions. | B01 | done | RESEARCH.md and evidence/* reference images/JSON record live public-page inspection and app/onboarding limits. |
| B03 | Produce three distinct original SVG logo studies with wordmark, monochrome, and 16/24/32 px samples. Record tradeoffs; recognition remains subject to Jason's judgment. | B02 | done | Three original studies in brand.js and assets/logos; rendered size/monochrome comparisons in index.html. |
| B04 | Compare sans-serif typography and propose consistent iconography, spacing, geometry, and focus/interaction treatment. Use real control labels and numerical samples. | B02 | done | Three local OFL font families and original outline icon specimens implemented. |
| B05 | Define ten palettes, each with a color-theory rationale and Light/Dim/Dark tokens. Keep identity and semantic meanings stable. Dark retains color and depth. | B04 | done | Ten rationale-bearing palettes and 30 mode token sets in brand.js and assets/palettes.json. |
| B06 | Build a local navigable HTML brand board with logo/type comparisons, ten-palette and three-mode selectors, and representative component states. Clearly mark samples. | B03, B04, B05 | done | index.html, styles.css, board.js provide local interactive brand comparisons and sample states. |
| B07 | Verify the brand board at mobile, desktop, and ultrawide widths, keyboard operation, focus, reduced motion where applicable, and contrast across all 30 palette/mode combinations. Save reproducible checks and browser evidence; flag missing checks honestly. | B06 | done | VERIFY.md and three evidence/*verification.json reports record contrast, 240 layouts, keyboard, targets, downloads, fallback and author screenshot checks with explicit limits. |
| B08 | Deliver the local entry path, review instructions, recommendation, and evidence/limitations. Brand board is ready for review, not an approved identity. | B07 | done | index.html entry page, README.md review instructions and VERIFY.md limitations delivered as a review-ready design package. No brand approval implied. |
| B09 | Obtain Jason's logo, typography, iconography, palette, and mode decisions; iterate the brand board as requested. Acceptance owner: Jason. | B08 | ready | First feedback received: Manrope and themes liked; logo has an unintended robot-crotch association. Revise logo direction, retain palette work, and use Manrope in the next preview. See DECISIONS.md. |
## Phase 2: five dashboard alternatives
Jason removed logo/iconography completion as a prerequisite for dashboard design. Proceed with Manrope, the existing ten palettes and three appearances, a text wordmark, and provisional labeled UI icons. B09 remains separate unfinished brand work, not a dashboard blocker. All implementation tasks are owned by Dewey; selection and final acceptance belong to Jason.
| ID | Task and acceptance evidence | Dependencies | Status | Next action |
| --- | --- | --- | --- | --- |
| D01 | Research current docs/plans and save a source-linked feature inventory. Distinguish implemented, planned, and owner-proposed capabilities. | B08 and owner gate revision | ready | Read current foundation feature sources, not the v1 UI. Final logo/iconography is not required. |
| D02 | Define shared routes, primary flows, states, sample data, and five genuinely different dashboard/navigation styles. | D01 | waiting | Establish comparable coverage across designs. |
| D03 | Build a central HTML index linking all five navigable, feature-rich mockups. Apply Manrope, ten palettes, and three modes consistently; use a text wordmark and provisional labeled icons until identity work is finalized. | D02 | waiting | Build shared prototype resources and distinct layouts. |
| D04 | Verify mobile/full-width/ultrawide layout, navigation, primary flows, keyboard access, and loading/empty/error/success/disabled/long-content states. Simulate unsupported features honestly. | D03 | waiting | Exercise each design in a browser and record evidence. |
| D05 | Deliver the comparison and obtain Jason's design selection. | D04 | waiting | Provide a short review script and wait for selection. |
## Phase 3: selected HTML design
| ID | Task and acceptance evidence | Dependencies | Status | Next action |
| --- | --- | --- | --- | --- |
| I01 | Record Jason's selected design, change requests, and newly requested features. | D05 | waiting | Turn feedback into bounded prototype tasks. |
| I02 | Iterate and reverify the chosen HTML mockup through explicit owner acceptance. Record unsupported backend requirements separately. | I01 | waiting | Implement approved prototype revisions only. |
| I03 | Prepare design assets, tokens, interaction specification, and backend dependency notes for a separately authorized coding/integration phase. | I02 | waiting | Deliver handoff without starting integration. |
## Boundaries and recovery
- Keep working artifacts here. Preserve unrelated repository work and the CURRENT.md inspector queue.
- No v1 UI inspection, backend integration, credentials, live fleet changes, publication, commit, or push.
- Do not claim unperformed browser checks, approved branding, or backend support.
- No numeric budget supplied. No external requests, watches, or uncertain operations outstanding.
- Next action: D01 feature inventory, then D02-D05 five dashboard alternatives. Logo/iconography refinement is non-blocking under Jason's revised direction. The completed first goal has not been restarted.
- The operator goal ends at B08, a review-ready brand board with documented limits. The extension owns its completion status. B09 is not automatically accepted. Later authorized work covers brand iteration or subsequent phases.
+61
View File
@@ -0,0 +1,61 @@
# Brand-board verification
Author: Dewey. Date: 2026-09-08. Scope: local interactive brand prototype, ready for review, not an integrated product or approved identity.
## Reproduce
From `/mnt/storage/src/mosaic-stack`:
```sh
node --check agents/dewey/work/wui/brand.js
node --check agents/dewey/work/wui/board.js
node agents/dewey/work/wui/checks/verify.mjs
node agents/dewey/work/wui/checks/detail-checks.mjs
node agents/dewey/work/wui/checks/final-checks.mjs
```
Environment used: Node 26.8.1, Chromium 152.0.7977.75 on Arch Linux. The CDP helper uses `/usr/bin/chromium`, or the `CHROMIUM` environment variable. Tests create a fresh temporary browser profile, open the entry page by file URL, save evidence here, and remove the profile at completion. No authenticated browser profile or Mosaic backend is used. There are no npm dependencies for this board or these tests.
`checks/assets.mjs` regenerates standalone SVGs and palette JSON from brand.js. `checks/fetch-fonts.py` refreshes the public Google Fonts WOFF2/OFL assets and needs network access. Neither is needed just to view or verify the current board. `checks/references.mjs` repeats the public reference-site inspection and also needs network access.
## Results
| Requirement | Result | Evidence |
| --- | --- | --- |
| Three distinct logo concepts | pass for review presentation | Assembly, Relay, Aperture rendered in identity cards, standalone SVGs, small monochrome samples, and selectable header/wordmark specimen. Author inspected screenshots. Recognition and final brand suitability are still Jason's decision. |
| Sans-serif alternatives and coherent icons | pass | Three locally loaded families with four weights each and license files. Eight labeled navigation icons use one original 24-unit/1.75-stroke family, shared with feedback symbols. |
| Ten theory-backed palettes, all three appearances | pass | Ten palettes carry named harmony relationships and explicit hue anchors in brand.js and the board. Thirty token sets generated. Palette/mode controls tested through their real change/click handlers. |
| Token contrast, A11Y-01/02 | pass for declared pairs | 840 unrounded ratio checks in verification.json. Normal text/action-label minimum observed 4.503925718129755:1, boundary/focus minimum 3.704773189325781:1. Checks cover normal/muted/action/accent/status text across canvas, surface, raised surfaces; borders/focus across those surfaces; on-action text on action. Decorative dividers and disabled controls use criterion exceptions. |
| Rendered text contrast | pass for sampled DOM text | 274 text/control samples per combination, 8,220 total. Computed foreground and solid ancestor backgrounds, qualifying large-text thresholds, minimum observed 4.504658476260286:1. This is not an image/gradient algorithm or a full accessibility audit. |
| Color-independent meaning, A11Y-03 | pass | Selection uses Selected labels and pressed/checked state. Status uses text plus icons. Author inspected the rendered component section. |
| Keyboard operation and focus, A11Y-05/06 | pass for tested flows | Native select and radio-arrow changes; Enter/Space selection buttons; Tab/Shift+Tab between sample fields; error recovery; skip link moves focus to main. Focus ring measured at 3 px solid. Short-screen sidebar focus stayed inside the 768 px viewport after adding sidebar scrolling. Chromium accessibility tree reports accessible names for all 60 interactive elements. This is not a screen-reader test. |
| Target size, A11Y-04 | pass for measured controls | Enabled buttons, fields, radio inputs, sidebar links, brand link and review link meet 24 px dimensions at 320 and 1440 widths. Inline footer/prose links use the inline-text exception. Most controls are at least 44 px tall. |
| Responsive/full-width layout, A11Y-07 | pass for measured layouts | All 30 combinations at 320, 390, 768, 960, 1440, 1920, 2560, 3440 CSS px. 240 layout checks, no page overflow. Ten additional checks cover both sides of the 700, 960, 1200, 1700, and 2400 breakpoints. Author inspected mobile, desktop, and 3440-wide screenshots; five palette columns use ultrawide space without unbounded prose. |
| Text enlargement/spacing, A11Y-07/08 | pass for tested overrides | 320 px reflow with WCAG text-spacing overrides, 200% root size, and separately doubling every element's computed font size including authored px values. Initial full-text expansion overflowed the review grid and small-size labels; minimum-width/wrapping fixes passed retest and screenshot inspection. Browser-native zoom was not exercised. |
| Reduced motion, A11Y-10 | pass | Emulated reduced-motion media preference; theme and keyboard controls remain usable. Board state changes do not rely on animation. |
| Loading/empty/error/success/disabled states | pass as labeled specimens | Tested all five selectable states, loading's disabled action, success button, preserved input after error. No actual request or project creation occurs. |
| Long content and failure fallback | pass for tested cases | Wrapped headings/labels and doubled text; font loads blocked and browser storage denied in isolated Chromium, with working controls and no page overflow at 320. Malformed saved preference JSON recovers to default. Input has a 160-character limit and native horizontal text-field scrolling. |
| Review notes and token downloads | pass | Browser downloads captured in evidence/downloads and contents checked. Note download contains test review text; palette JSON includes Light/Dim/Dark tokens. These files are author test fixtures, not Jason's decisions. |
| Offline resource/link integrity | pass | CDP resource tree showed 11 loaded resources, all local file URLs. Source asset links and internal anchors resolve. Three real font families load. No remote font/CDN/backend request belongs to the board. |
| Public site completeness | not applicable to this local review artifact | Single file with section anchors, no public deployment or app router. About/Contact/legal pages, HTTP 404 behavior, consent management, billing and account workflows are outside this prototype. Storage use is explained beside controls and notes. No legal compliance claim. |
| Reference sites | pass for public-page inspection, app behavior not verified | RESEARCH.md and reference screenshots. No v1 inspection. T3 application theme switching and Buzz's installed application wizard were not exercised. |
## Visual fixes and test corrections
- Early reference screenshots captured entrance animations, not completed pages. Re-captured after a bounded animation allowance.
- CDP Enter needed its character value, and Shift uses modifier bit 8. Fixed the test driver rather than changing working controls to accommodate a faulty test.
- Added scrollable desktop preview controls so keyboard focus remains available on short screens.
- Doubled text exposed a review-column minimum-width problem and logo-size row wrapping. Fixed and rechecked.
- A 320 px screenshot exposed a clipped Conversations label. Changed narrow icon layout to two columns and allowed long labels to wrap. Rechecked the actual rendering.
- Corrected draft hue anchors so named complementary/triadic/split-complementary relationships match their stated angles. Regenerated assets and re-ran contrast/layout suites.
- File-URL resources did not populate the expected Performance entries. The final resource check uses Chromium's Page.getResourceTree instead; its resource URLs are all local.
## Verification limits and remaining decisions
- Tested one installed desktop Chromium engine. Safari, Firefox, native mobile devices, touchscreen behavior, assistive technology, OS forced colors, and browser-native zoom are not verified.
- Browser viewport emulation and doubled text are useful evidence, not equivalent to testing every physical display and accessibility configuration.
- Contrast assertions and Chromium accessibility-tree names do not establish full WCAG conformance. They cover the listed cases.
- Only Latin font subsets are bundled. Multilingual typography and fallback coverage need a later product brief.
- Logos are original author studies, not independently reviewed, user-tested, trademark-cleared, or final production assets. Small-size optical refinements await selection.
- No independent technical review, issue lifecycle, repository delivery suites, integration, deployment, commits, or pushes were performed for this standalone design package. Those delivery gates remain separate if the prototype is promoted into product work.
- Jason has not approved branding. B09 and all dashboard tasks remain behind that human gate.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,93 @@
Copyright 2014 The DM Sans Project Authors (https://github.com/googlefonts/dm-fonts)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,7 @@
DM Sans
CSS: https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&display=swap
License: https://raw.githubusercontent.com/google/fonts/main/ofl/dmsans/OFL.txt
400: https://fonts.gstatic.com/s/dmsans/v17/rP2Yp2ywxg089UriI5-g4vlH9VoD8Cmcqbu0-K4.woff2
500: https://fonts.gstatic.com/s/dmsans/v17/rP2Yp2ywxg089UriI5-g4vlH9VoD8Cmcqbu0-K4.woff2
600: https://fonts.gstatic.com/s/dmsans/v17/rP2Yp2ywxg089UriI5-g4vlH9VoD8Cmcqbu0-K4.woff2
700: https://fonts.gstatic.com/s/dmsans/v17/rP2Yp2ywxg089UriI5-g4vlH9VoD8Cmcqbu0-K4.woff2
@@ -0,0 +1,93 @@
Copyright © 2017 IBM Corp. with Reserved Font Name "Plex"
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,7 @@
IBM Plex Sans
CSS: https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@400;500;600;700&display=swap
License: https://raw.githubusercontent.com/google/fonts/main/ofl/ibmplexsans/OFL.txt
400: https://fonts.gstatic.com/s/ibmplexsans/v23/zYXzKVElMYYaJe8bpLHnCwDKr932-G7dytD-Dmu1syxeKYY.woff2
500: https://fonts.gstatic.com/s/ibmplexsans/v23/zYXzKVElMYYaJe8bpLHnCwDKr932-G7dytD-Dmu1syxeKYY.woff2
600: https://fonts.gstatic.com/s/ibmplexsans/v23/zYXzKVElMYYaJe8bpLHnCwDKr932-G7dytD-Dmu1syxeKYY.woff2
700: https://fonts.gstatic.com/s/ibmplexsans/v23/zYXzKVElMYYaJe8bpLHnCwDKr932-G7dytD-Dmu1syxeKYY.woff2
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,93 @@
Copyright 2018 The Manrope Project Authors (https://github.com/sharanda/manrope)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,7 @@
Manrope
CSS: https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700&display=swap
License: https://raw.githubusercontent.com/google/fonts/main/ofl/manrope/OFL.txt
400: https://fonts.gstatic.com/s/manrope/v20/xn7gYHE41ni1AdIRggexSg.woff2
500: https://fonts.gstatic.com/s/manrope/v20/xn7gYHE41ni1AdIRggexSg.woff2
600: https://fonts.gstatic.com/s/manrope/v20/xn7gYHE41ni1AdIRggexSg.woff2
700: https://fonts.gstatic.com/s/manrope/v20/xn7gYHE41ni1AdIRggexSg.woff2
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 56 56" fill="#215fac" role="img" aria-label="Mosaic Stack Aperture concept"><path fill-rule="evenodd" d="M4 4h30v10H14v28H4zm34 0 14 14v34H18V18h16v10h-6v14h14V22l-4-4z"/></svg>

After

Width:  |  Height:  |  Size: 231 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 56 56" fill="#215fac" role="img" aria-label="Mosaic Stack Assembly concept"><path d="M4 4h10v24H4zM18 4l12 12-7 7-5-5zM34 4v14l-5 5-7-7zM38 4h10v24H38z" transform="translate(2 10)"/></svg>

After

Width:  |  Height:  |  Size: 242 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 56 56" fill="#215fac" role="img" aria-label="Mosaic Stack Relay concept"><path fill-rule="evenodd" d="M4 18 18 4h12l10 10-8 8-8-8h-2L14 22v2l8 8-8 8L4 30zm48 8L38 40H26L16 30l8-8 8 8h2l8-8v-2l-8-8 8-8 10 10z" transform="translate(0 6)"/></svg>

After

Width:  |  Height:  |  Size: 297 B

+615
View File
@@ -0,0 +1,615 @@
{
"prototype": true,
"palettes": [
{
"id": "harbor",
"name": "Harbor",
"hue": 214,
"sat": 70,
"accent": 34,
"accentSat": 63,
"theory": "Complementary",
"note": "Clear blue with a restrained copper counterpoint. The warm accent balances cool navigation and gives selected details a second voice.",
"use": "Proposed default. Blue without the blue-purple gradient.",
"modes": {
"light": {
"canvas": "#f3f5f7",
"surface": "#ffffff",
"raised": "#e6eaef",
"text": "#434d5b",
"muted": "#5e6978",
"line": "#ced5df",
"border": "#636e7e",
"action": "#2266bf",
"onAction": "#ffffff",
"accent": "#8d5e20",
"focus": "#2266bf",
"success": "#287658",
"warning": "#8f5c19",
"danger": "#ba2e26"
},
"dim": {
"canvas": "#242d38",
"surface": "#2e3947",
"raised": "#384556",
"text": "#d6dbe1",
"muted": "#a9b1bc",
"line": "#47576c",
"border": "#a4acb7",
"action": "#8ab4ea",
"onAction": "#10141a",
"accent": "#e1b47a",
"focus": "#8ab4ea",
"success": "#85d5b7",
"warning": "#e7b574",
"danger": "#ea9d99"
},
"dark": {
"canvas": "#12161c",
"surface": "#1c232b",
"raised": "#28323e",
"text": "#b9c1cb",
"muted": "#a4acb7",
"line": "#384556",
"border": "#a4acb7",
"action": "#74a6e7",
"onAction": "#10141a",
"accent": "#e1b47a",
"focus": "#74a6e7",
"success": "#85d5b7",
"warning": "#e7b574",
"danger": "#e37d78"
}
}
},
{
"id": "carmine",
"name": "Carmine",
"hue": 350,
"sat": 65,
"accent": 176,
"accentSat": 42,
"theory": "Near-complementary",
"note": "A red-led identity with a cool turquoise counterpoint. Rose-tinted neutrals keep the red from covering every surface.",
"use": "For a red preference. Errors still use an icon and explicit wording.",
"modes": {
"light": {
"canvas": "#f7f3f3",
"surface": "#ffffff",
"raised": "#efe7e8",
"text": "#5e4549",
"muted": "#7b6065",
"line": "#deced1",
"border": "#7e6367",
"action": "#b92740",
"onAction": "#ffffff",
"accent": "#2e706c",
"focus": "#b92740",
"success": "#287658",
"warning": "#8f5c19",
"danger": "#ba2e26"
},
"dim": {
"canvas": "#372528",
"surface": "#462f33",
"raised": "#55393e",
"text": "#ded3d5",
"muted": "#bca9ac",
"line": "#6b484e",
"border": "#b7a4a7",
"action": "#e996a4",
"onAction": "#10141a",
"accent": "#8bd0cb",
"focus": "#e996a4",
"success": "#85d5b7",
"warning": "#e7b574",
"danger": "#e99995"
},
"dark": {
"canvas": "#1b1214",
"surface": "#2b1d1f",
"raised": "#3d292c",
"text": "#c9b6b9",
"muted": "#b7a4a7",
"line": "#55393e",
"border": "#b7a4a7",
"action": "#e2788a",
"onAction": "#10141a",
"accent": "#8bd0cb",
"focus": "#e2788a",
"success": "#85d5b7",
"warning": "#e7b574",
"danger": "#e37d78"
}
}
},
{
"id": "atlantic",
"name": "Atlantic",
"hue": 199,
"sat": 72,
"accent": 170,
"accentSat": 52,
"theory": "Analogous",
"note": "Ocean blue and teal sit close on the hue wheel. Their shared cool bias makes a quieter combination than an opposing accent.",
"use": "A cohesive blue-green alternative with low visual rivalry.",
"modes": {
"light": {
"canvas": "#f3f6f7",
"surface": "#ffffff",
"raised": "#e6ecef",
"text": "#3f4e55",
"muted": "#5c6d75",
"line": "#cdd9df",
"border": "#63757e",
"action": "#19719a",
"onAction": "#ffffff",
"accent": "#257467",
"focus": "#19719a",
"success": "#287658",
"warning": "#935f1a",
"danger": "#ba2e26"
},
"dim": {
"canvas": "#243238",
"surface": "#2e3f47",
"raised": "#384d57",
"text": "#e2e7e9",
"muted": "#afbbc0",
"line": "#46606d",
"border": "#a4b1b7",
"action": "#73c3e8",
"onAction": "#10141a",
"accent": "#83d8ca",
"focus": "#73c3e8",
"success": "#85d5b7",
"warning": "#e7b574",
"danger": "#edaaa6"
},
"dark": {
"canvas": "#12191c",
"surface": "#1c272b",
"raised": "#28373e",
"text": "#bcc8cd",
"muted": "#a4b1b7",
"line": "#384d57",
"border": "#a4b1b7",
"action": "#73c3e8",
"onAction": "#10141a",
"accent": "#83d8ca",
"focus": "#73c3e8",
"success": "#85d5b7",
"warning": "#e7b574",
"danger": "#e4817c"
}
}
},
{
"id": "terracotta",
"name": "Terracotta",
"hue": 18,
"sat": 60,
"accent": 198,
"accentSat": 44,
"theory": "Complementary",
"note": "Fired-clay orange meets a desaturated steel blue. Warm neutral surfaces connect the palette without needing a beige wash everywhere.",
"use": "An earthier option for writing and personal work.",
"modes": {
"light": {
"canvas": "#f7f4f3",
"surface": "#ffffff",
"raised": "#eee9e7",
"text": "#584841",
"muted": "#78665e",
"line": "#ded3cf",
"border": "#7e6b63",
"action": "#a74f2a",
"onAction": "#ffffff",
"accent": "#356f88",
"focus": "#a74f2a",
"success": "#287658",
"warning": "#8f5c19",
"danger": "#ba2e26"
},
"dim": {
"canvas": "#362b26",
"surface": "#453630",
"raised": "#54423b",
"text": "#e5dfdc",
"muted": "#beb2ac",
"line": "#695349",
"border": "#b7a9a4",
"action": "#e2a68d",
"onAction": "#10141a",
"accent": "#89bcd1",
"focus": "#e2a68d",
"success": "#85d5b7",
"warning": "#e7b574",
"danger": "#eba29e"
},
"dark": {
"canvas": "#1b1513",
"surface": "#2a211d",
"raised": "#3c2f2a",
"text": "#cbbeb9",
"muted": "#b7a9a4",
"line": "#54423b",
"border": "#b7a9a4",
"action": "#de9a7c",
"onAction": "#10141a",
"accent": "#89bcd1",
"focus": "#de9a7c",
"success": "#85d5b7",
"warning": "#e7b574",
"danger": "#e37d78"
}
}
},
{
"id": "aubergine",
"name": "Aubergine",
"hue": 287,
"sat": 38,
"accent": 47,
"accentSat": 46,
"theory": "Triadic pair",
"note": "Muted plum and ochre sit 120 degrees apart on the hue wheel. The third triadic hue, teal, is left out so the interface has two brand accents rather than three.",
"use": "A deliberate purple option for users who want it, without the AI gradient.",
"modes": {
"light": {
"canvas": "#f5f4f6",
"surface": "#ffffff",
"raised": "#ece8ed",
"text": "#59455e",
"muted": "#75607b",
"line": "#d9d2db",
"border": "#78637e",
"action": "#88469b",
"onAction": "#ffffff",
"accent": "#77672c",
"focus": "#88469b",
"success": "#287658",
"warning": "#8f5c19",
"danger": "#ba2e26"
},
"dim": {
"canvas": "#312933",
"surface": "#3e3441",
"raised": "#4c3f50",
"text": "#e1d9e3",
"muted": "#baacbe",
"line": "#5f4f63",
"border": "#b3a4b7",
"action": "#cba4d6",
"onAction": "#10141a",
"accent": "#d3c388",
"focus": "#cba4d6",
"success": "#85d5b7",
"warning": "#e7b574",
"danger": "#ea9d99"
},
"dark": {
"canvas": "#18141a",
"surface": "#262028",
"raised": "#362d39",
"text": "#c7b9cb",
"muted": "#b3a4b7",
"line": "#4c3f50",
"border": "#b3a4b7",
"action": "#bf8ecc",
"onAction": "#10141a",
"accent": "#d3c388",
"focus": "#bf8ecc",
"success": "#85d5b7",
"warning": "#e7b574",
"danger": "#e37d78"
}
}
},
{
"id": "mineral",
"name": "Mineral",
"hue": 171,
"sat": 47,
"accent": 351,
"accentSat": 42,
"theory": "Complementary",
"note": "Deep teal and dusty rose oppose each other while keeping saturation restrained. Blue-green tinted layers carry the identity in dark mode.",
"use": "Cool surfaces with a small warm punctuation.",
"modes": {
"light": {
"canvas": "#f3f6f6",
"surface": "#ffffff",
"raised": "#e8eded",
"text": "#3d524f",
"muted": "#586f6c",
"line": "#d0dcda",
"border": "#637e7a",
"action": "#2a7469",
"onAction": "#ffffff",
"accent": "#9f414f",
"focus": "#2a7469",
"success": "#287658",
"warning": "#935f1a",
"danger": "#ba2e26"
},
"dim": {
"canvas": "#273432",
"surface": "#324340",
"raised": "#3d514e",
"text": "#e5ebea",
"muted": "#b2c2c0",
"line": "#4d6662",
"border": "#a4b7b4",
"action": "#87d4c8",
"onAction": "#10141a",
"accent": "#e0b3ba",
"focus": "#87d4c8",
"success": "#85d5b7",
"warning": "#e7b574",
"danger": "#eeaeaa"
},
"dark": {
"canvas": "#141a19",
"surface": "#1f2927",
"raised": "#2c3a38",
"text": "#b9cbc8",
"muted": "#a4b7b4",
"line": "#3d514e",
"border": "#a4b7b4",
"action": "#87d4c8",
"onAction": "#10141a",
"accent": "#d18f99",
"focus": "#87d4c8",
"success": "#85d5b7",
"warning": "#e7b574",
"danger": "#e58580"
}
}
},
{
"id": "cobalt",
"name": "Cobalt",
"hue": 229,
"sat": 75,
"accent": 49,
"accentSat": 63,
"theory": "Complementary",
"note": "A stronger royal blue meets a small amber accent. The high hue separation is controlled by using amber only in secondary details.",
"use": "The most assertive blue option. No large yellow surfaces.",
"modes": {
"light": {
"canvas": "#f3f3f7",
"surface": "#ffffff",
"raised": "#e6e8ef",
"text": "#454a5e",
"muted": "#60657b",
"line": "#cdd1df",
"border": "#63687e",
"action": "#1c3bc4",
"onAction": "#ffffff",
"accent": "#79671b",
"focus": "#1c3bc4",
"success": "#277255",
"warning": "#8f5c19",
"danger": "#ba2e26"
},
"dim": {
"canvas": "#242838",
"surface": "#2e3248",
"raised": "#383d57",
"text": "#d0d2dc",
"muted": "#a6aab9",
"line": "#464d6d",
"border": "#a4a7b7",
"action": "#94a5f0",
"onAction": "#10141a",
"accent": "#e1ce7a",
"focus": "#94a5f0",
"success": "#85d5b7",
"warning": "#e7b574",
"danger": "#e89591"
},
"dark": {
"canvas": "#12141c",
"surface": "#1c1f2c",
"raised": "#282c3e",
"text": "#b6b9c9",
"muted": "#a4a7b7",
"line": "#383d57",
"border": "#a4a7b7",
"action": "#798eec",
"onAction": "#10141a",
"accent": "#e1ce7a",
"focus": "#798eec",
"success": "#85d5b7",
"warning": "#e7b574",
"danger": "#e37d78"
}
}
},
{
"id": "rosewood",
"name": "Rosewood",
"hue": 329,
"sat": 47,
"accent": 209,
"accentSat": 39,
"theory": "Triadic pair",
"note": "Dusty pink and steel blue occupy two points of a triadic relationship. The third, yellow-green, is omitted to avoid an overly colorful interface.",
"use": "A softer warm identity that does not become pastel text.",
"modes": {
"light": {
"canvas": "#f6f3f5",
"surface": "#ffffff",
"raised": "#ede8eb",
"text": "#5e4552",
"muted": "#7b606e",
"line": "#dcd0d6",
"border": "#7e6371",
"action": "#a53b72",
"onAction": "#ffffff",
"accent": "#416c95",
"focus": "#a53b72",
"success": "#287658",
"warning": "#8f5c19",
"danger": "#ba2e26"
},
"dim": {
"canvas": "#34272e",
"surface": "#43323b",
"raised": "#513d48",
"text": "#e1d6db",
"muted": "#beacb5",
"line": "#664d5a",
"border": "#b7a4ae",
"action": "#dc9ebe",
"onAction": "#10141a",
"accent": "#95b3d0",
"focus": "#dc9ebe",
"success": "#85d5b7",
"warning": "#e7b574",
"danger": "#ea9d99"
},
"dark": {
"canvas": "#1a1417",
"surface": "#291f24",
"raised": "#3a2c33",
"text": "#cbb9c2",
"muted": "#b7a4ae",
"line": "#513d48",
"border": "#b7a4ae",
"action": "#d487af",
"onAction": "#10141a",
"accent": "#8eaecd",
"focus": "#d487af",
"success": "#85d5b7",
"warning": "#e7b574",
"danger": "#e37d78"
}
}
},
{
"id": "graphite",
"name": "Graphite",
"hue": 216,
"sat": 9,
"accent": 216,
"accentSat": 12,
"theory": "Monochromatic",
"note": "One blue-gray hue uses value and saturation changes instead of a second brand hue. Semantic status colors remain independent.",
"use": "Minimal chroma for content-heavy work. Hierarchy comes from contrast.",
"modes": {
"light": {
"canvas": "#f5f5f5",
"surface": "#ffffff",
"raised": "#eaeaeb",
"text": "#434d5b",
"muted": "#5e6978",
"line": "#d5d6d7",
"border": "#636e7e",
"action": "#616975",
"onAction": "#ffffff",
"accent": "#5e6978",
"focus": "#616975",
"success": "#287658",
"warning": "#8f5c19",
"danger": "#ba2e26"
},
"dim": {
"canvas": "#2d2e2f",
"surface": "#393a3c",
"raised": "#454749",
"text": "#dfe2e7",
"muted": "#afb6c0",
"line": "#57595c",
"border": "#a4abb7",
"action": "#b1b6be",
"onAction": "#10141a",
"accent": "#afb6c0",
"focus": "#b1b6be",
"success": "#85d5b7",
"warning": "#e7b574",
"danger": "#eba29e"
},
"dark": {
"canvas": "#161718",
"surface": "#232425",
"raised": "#323334",
"text": "#bcc3cd",
"muted": "#a4abb7",
"line": "#454749",
"border": "#a4abb7",
"action": "#a6acb5",
"onAction": "#10141a",
"accent": "#a4abb7",
"focus": "#a6acb5",
"success": "#85d5b7",
"warning": "#e7b574",
"danger": "#e37d78"
}
}
},
{
"id": "grove",
"name": "Grove",
"hue": 146,
"sat": 37,
"accent": 356,
"accentSat": 39,
"theory": "Split-complementary pair",
"note": "Muted forest green meets dusty rose, 30 degrees to one side of its magenta complement. The second split accent is omitted. Low-saturation surfaces keep green from dominating.",
"use": "An optional green palette for other preferences, not the proposed default.",
"modes": {
"light": {
"canvas": "#f4f6f5",
"surface": "#ffffff",
"raised": "#e8edea",
"text": "#3d5246",
"muted": "#586f62",
"line": "#d2dbd6",
"border": "#637e6e",
"action": "#377752",
"onAction": "#ffffff",
"accent": "#9c444a",
"focus": "#377752",
"success": "#287658",
"warning": "#935f1a",
"danger": "#ba2e26"
},
"dim": {
"canvas": "#29332d",
"surface": "#34413a",
"raised": "#3f4f46",
"text": "#e2e9e5",
"muted": "#afc0b6",
"line": "#4f6358",
"border": "#a4b7ac",
"action": "#8fcca9",
"onAction": "#10141a",
"accent": "#ddb1b4",
"focus": "#8fcca9",
"success": "#85d5b7",
"warning": "#e7b574",
"danger": "#edaaa6"
},
"dark": {
"canvas": "#141917",
"surface": "#202823",
"raised": "#2d3932",
"text": "#b9cbc1",
"muted": "#a4b7ac",
"line": "#3f4f46",
"border": "#a4b7ac",
"action": "#8fcca9",
"onAction": "#10141a",
"accent": "#cd8e92",
"focus": "#8fcca9",
"success": "#85d5b7",
"warning": "#e7b574",
"danger": "#e58580"
}
}
}
]
}
+102
View File
@@ -0,0 +1,102 @@
(() => {
'use strict';
const B = window.Brand;
const $ = id => document.getElementById(id);
const modes = ['light','dim','dark'];
const modeName = mode => mode[0].toUpperCase() + mode.slice(1);
const defaults = {palette:'harbor',font:'dm',mark:'mosaic',mode:matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light'};
let state = {...defaults};
let storageAvailable = true;
try {
const saved = JSON.parse(localStorage.getItem('mosaic-brand-preview-v1') || '{}');
for (const [key, items] of Object.entries({palette:B.palettes.map(p=>p.id),font:B.fonts.map(f=>f.id),mark:B.logos.map(l=>l.id),mode:modes})) {
if (items.includes(saved?.[key])) state[key]=saved[key];
}
$('review-notes').value = localStorage.getItem('mosaic-brand-notes-v1') || '';
} catch { storageAvailable = false; }
function announce(text) {$('announcement').textContent=text;}
function persist() {
try {localStorage.setItem('mosaic-brand-preview-v1',JSON.stringify(state));}
catch {storageAvailable=false;announce('Browser storage is unavailable. Download your review notes before closing.');}
}
for(const [id, data] of [['palette',B.palettes],['font',B.fonts],['mark',B.logos]]) {
$(id).innerHTML=data.map(x=>`<option value="${x.id}">${x.name}</option>`).join('');
$(id).addEventListener('change',event=>{state[id]=event.target.value;update();});
}
document.querySelectorAll('[name=mode]').forEach(input=>input.addEventListener('change',()=>{state.mode=input.value;update();}));
$('logo-grid').innerHTML=B.logos.map((l,i)=>`<article class="study-card" data-mark-card="${l.id}">
<div class="card-kicker"><span>${String(i+1).padStart(2,'0')} / ${l.family}</span><span class="selection-label" data-mark-label="${l.id}"></span></div>
<div class="logo-display">${B.logo(l.id)}</div><h3>${l.name}</h3><p>${l.note}</p>
<div class="size-strip" aria-label="${l.name} monochrome size samples">${[16,24,32].map(size=>`<span>${B.logo(l.id,size)}${size} px</span>`).join('')}<span>${B.logo(l.id,24).replace('class="logo"','class="logo reverse"')}Reverse</span></div>
<p class="tradeoff">${l.tradeoff}</p><button type="button" class="choose" data-choose-mark="${l.id}" aria-pressed="false">Use ${l.name}</button></article>`).join('');
$('font-grid').innerHTML=B.fonts.map(f=>`<article class="study-card" data-font-card="${f.id}"><div class="card-kicker"><span>${f.detail}</span><span class="selection-label" data-font-label="${f.id}"></span></div>
<div style='font-family:${f.family}'><h3 class="font-title">${f.name}</h3><div class="type-specimen"><p class="type-heading">A place for your next idea.</p><p>Plan a project, write a chapter, or ask an agent to help. Start with what you need.</p><p class="numerals">0123456789<br>Il1 O0 · 12:48 · 1,024</p></div></div><p>${f.note}</p><button type="button" class="choose" data-choose-font="${f.id}" aria-pressed="false">Use ${f.name}</button></article>`).join('');
$('palette-grid').innerHTML=B.palettes.map(p=>{
const t=B.tokens(p,'light');
return `<article class="palette-card" data-palette-card="${p.id}"><h3>${p.name}<span data-palette-label="${p.id}"></span></h3><div class="palette-swatches" aria-hidden="true">${['action','accent','raised','canvas'].map(role=>`<i style="background:${t[role]}"></i>`).join('')}</div><p class="theory">${p.theory} · ${p.hue}° / ${p.accent}°</p><p>${p.note}</p><p class="palette-use">${p.use}</p><div class="palette-modes" aria-label="${p.name} appearance">${modes.map(mode=>{const t=B.tokens(p,mode);return `<button type="button" data-palette="${p.id}" data-mode="${mode}" aria-label="Preview ${p.name} in ${modeName(mode)}" aria-pressed="false" style="--mini-surface:${t.surface};--mini-text:${t.text};--mini-border:${t.border};--mini-raised:${t.raised}">${modeName(mode)}</button>`;}).join('')}</div></article>`;
}).join('');
$('icon-grid').innerHTML=[['home','Home'],['conversation','Conversations'],['projects','Projects'],['agents','Agents'],['people','People'],['board','Board'],['extensions','Extensions'],['search','Search']].map(([id,label])=>`<div class="icon-specimen">${B.icon(id)}<span>${label}</span></div>`).join('');
document.querySelectorAll('[data-icon]').forEach(el=>el.innerHTML=B.icon(el.dataset.icon));
document.querySelectorAll('[data-choose-mark]').forEach(button=>button.addEventListener('click',()=>{state.mark=button.dataset.chooseMark;update();}));
document.querySelectorAll('[data-choose-font]').forEach(button=>button.addEventListener('click',()=>{state.font=button.dataset.chooseFont;update();}));
document.querySelectorAll('[data-palette][data-mode]').forEach(button=>button.addEventListener('click',()=>{state.palette=button.dataset.palette;state.mode=button.dataset.mode;update();}));
function update(shouldAnnounce=true) {
const p=B.palettes.find(p=>p.id===state.palette), f=B.fonts.find(f=>f.id===state.font), l=B.logos.find(l=>l.id===state.mark);
const t=B.tokens(p,state.mode);
for(const [role,value] of Object.entries(t)) document.documentElement.style.setProperty('--'+role,value);
document.documentElement.style.setProperty('--font',f.family);
document.documentElement.style.colorScheme=state.mode==='light'?'light':'dark';
document.documentElement.dataset.mode=state.mode;
document.documentElement.dataset.palette=state.palette;
for(const id of ['palette','font','mark']) $(id).value=state[id];
document.querySelectorAll('[name=mode]').forEach(input=>input.checked=input.value===state.mode);
document.querySelectorAll('[data-logo]').forEach(el=>el.innerHTML=B.logo(state.mark));
$('current-palette').textContent=p.name;
$('current-mode').textContent=modeName(state.mode);
for(const [kind,data] of [['mark',B.logos],['font',B.fonts],['palette',B.palettes]]) {
data.forEach(item=>{
const chosen=item.id===state[kind];
document.querySelector(`[data-${kind}-card="${item.id}"]`).classList.toggle('is-selected',chosen);
document.querySelector(`[data-${kind}-label="${item.id}"]`).textContent=chosen?'Selected':'';
document.querySelector(`[data-choose-${kind}="${item.id}"]`)?.setAttribute('aria-pressed',String(chosen));
});
}
document.querySelectorAll('[data-palette][data-mode]').forEach(button=>button.setAttribute('aria-pressed',String(button.dataset.palette===state.palette && button.dataset.mode===state.mode)));
$('token-title').textContent=`${p.name} / ${modeName(state.mode)} tokens`;
$('tokens').innerHTML=Object.entries(t).map(([role,value])=>`<div><dt><i style="background:${value}" aria-hidden="true"></i>${role.replace('onAction','On action')}</dt><dd>${value.toUpperCase()}</dd></div>`).join('');
const summary=`${l.name} · ${f.name} · ${p.name} · ${modeName(state.mode)}`;
$('selection-summary').textContent=`Current preview: ${summary}.`;
persist();
if(shouldAnnounce) announce(`Preview changed to ${summary}.`);
}
const messages={ready:['conversation','Ready. Try a local success preview.'],loading:['dim','Loading specimen. No request is running. Choose another state to continue.'],empty:['plus','No projects in this example. Your next step would be to create one.'],error:['error','Could not save this example. Your text is unchanged. Use Preview success to try again.'],success:['check','Success preview. No project was created or saved to a server.']};
function sample() {
const state=$('sample-state').value, [icon,message]=messages[state];
$('sample-feedback').dataset.state=state;
$('sample-feedback').innerHTML=B.icon(icon)+`<span>${message}</span>`;
$('sample-action').disabled=state==='loading';
$('sample-title').setAttribute('aria-describedby','sample-help sample-feedback');
}
$('sample-state').addEventListener('change',sample);
$('sample-action').addEventListener('click',()=>{$('sample-state').value='success';sample();});
$('reset').addEventListener('click',()=>{state={...defaults};update();announce('Preview reset. Your review notes and example project name are unchanged.');});
function download(name,type,content) {
const url=URL.createObjectURL(new Blob([content],{type}));
const a=document.createElement('a');a.href=url;a.download=name;a.click();
// Browser downloads consume the URL before the next task; retain briefly for portability.
setTimeout(()=>URL.revokeObjectURL(url),1000);
announce(`${name} prepared for download. Check your browser downloads.`);
}
$('export').addEventListener('click',()=>{
const p=B.palettes.find(p=>p.id===state.palette);
download(`mosaic-${p.id}-tokens.json`,'application/json',JSON.stringify({prototype:true,palette:p.name,theory:p.theory,rationale:p.note,modes:Object.fromEntries(modes.map(mode=>[mode,B.tokens(p,mode)]))},null,2));
});
$('review-notes').addEventListener('input',()=>{
try{localStorage.setItem('mosaic-brand-notes-v1',$('review-notes').value);}catch{storageAvailable=false;announce('Notes cannot be stored in this browser. Download them before closing.');}
});
$('download-review').addEventListener('click',()=>{
download('mosaic-brand-review.txt','text/plain',`Mosaic Stack branding review\n${$('selection-summary').textContent}\n\n${$('review-notes').value||'No written notes yet.'}\n\nThese selections are review preferences, not an automatic approval.\n`);
});
update(false);sample();
if(!storageAvailable) announce('Browser storage is unavailable. The preview still works. Download notes to keep them.');
})();
+77
View File
@@ -0,0 +1,77 @@
/* Original brand studies. This file contains prototype design data, not an API. */
(function (root) {
const palettes = [
{id:'harbor', name:'Harbor', hue:214, sat:70, accent:34, accentSat:63, theory:'Complementary', note:'Clear blue with a restrained copper counterpoint. The warm accent balances cool navigation and gives selected details a second voice.', use:'Proposed default. Blue without the blue-purple gradient.'},
{id:'carmine', name:'Carmine', hue:350, sat:65, accent:176, accentSat:42, theory:'Near-complementary', note:'A red-led identity with a cool turquoise counterpoint. Rose-tinted neutrals keep the red from covering every surface.', use:'For a red preference. Errors still use an icon and explicit wording.'},
{id:'atlantic', name:'Atlantic', hue:199, sat:72, accent:170, accentSat:52, theory:'Analogous', note:'Ocean blue and teal sit close on the hue wheel. Their shared cool bias makes a quieter combination than an opposing accent.', use:'A cohesive blue-green alternative with low visual rivalry.'},
{id:'terracotta', name:'Terracotta', hue:18, sat:60, accent:198, accentSat:44, theory:'Complementary', note:'Fired-clay orange meets a desaturated steel blue. Warm neutral surfaces connect the palette without needing a beige wash everywhere.', use:'An earthier option for writing and personal work.'},
{id:'aubergine', name:'Aubergine', hue:287, sat:38, accent:47, accentSat:46, theory:'Triadic pair', note:'Muted plum and ochre sit 120 degrees apart on the hue wheel. The third triadic hue, teal, is left out so the interface has two brand accents rather than three.', use:'A deliberate purple option for users who want it, without the AI gradient.'},
{id:'mineral', name:'Mineral', hue:171, sat:47, accent:351, accentSat:42, theory:'Complementary', note:'Deep teal and dusty rose oppose each other while keeping saturation restrained. Blue-green tinted layers carry the identity in dark mode.', use:'Cool surfaces with a small warm punctuation.'},
{id:'cobalt', name:'Cobalt', hue:229, sat:75, accent:49, accentSat:63, theory:'Complementary', note:'A stronger royal blue meets a small amber accent. The high hue separation is controlled by using amber only in secondary details.', use:'The most assertive blue option. No large yellow surfaces.'},
{id:'rosewood', name:'Rosewood', hue:329, sat:47, accent:209, accentSat:39, theory:'Triadic pair', note:'Dusty pink and steel blue occupy two points of a triadic relationship. The third, yellow-green, is omitted to avoid an overly colorful interface.', use:'A softer warm identity that does not become pastel text.'},
{id:'graphite', name:'Graphite', hue:216, sat:9, accent:216, accentSat:12, theory:'Monochromatic', note:'One blue-gray hue uses value and saturation changes instead of a second brand hue. Semantic status colors remain independent.', use:'Minimal chroma for content-heavy work. Hierarchy comes from contrast.'},
{id:'grove', name:'Grove', hue:146, sat:37, accent:356, accentSat:39, theory:'Split-complementary pair', note:'Muted forest green meets dusty rose, 30 degrees to one side of its magenta complement. The second split accent is omitted. Low-saturation surfaces keep green from dominating.', use:'An optional green palette for other preferences, not the proposed default.'},
];
const fonts = [
{id:'dm', name:'DM Sans', family:'"DM Sans", system-ui, sans-serif', note:'Open, rounded forms without becoming playful. My first choice for a product that spans everyday work and professional tools.', detail:'Recommended balance'},
{id:'plex', name:'IBM Plex Sans', family:'"IBM Plex Sans", system-ui, sans-serif', note:'More engineered letterforms and a distinctive rhythm. Strong for dense labels and data; its technical character is more noticeable.', detail:'Precise and structured'},
{id:'manrope', name:'Manrope', family:'Manrope, system-ui, sans-serif', note:'Broad geometric forms give the wordmark more presence. Compare long control labels carefully because the wider forms use more space.', detail:'Geometric and expressive'},
];
const logos = [
{id:'mosaic', name:'Assembly', family:'An assembled M', note:'Four solid pieces form an M with an open center. The gaps suggest independent tools working together without using a puzzle-piece cliché.', tradeoff:'Most direct link to Mosaic. At 16 px, the two-unit gaps become fine seams.', paths:'<path d="M4 4h10v24H4zM18 4l12 12-7 7-5-5zM34 4v14l-5 5-7-7zM38 4h10v24H38z" transform="translate(2 10)"/>', recommended:true},
{id:'weave', name:'Relay', family:'An interlocking ribbon', note:'Two angular links cross to make a compact woven loop. The open counters suggest handoffs between people, agents, and tools.', tradeoff:'Strong standalone symbol, but less obviously an M. Check for resemblance to existing link marks before final adoption.', paths:'<path fill-rule="evenodd" d="M4 18 18 4h12l10 10-8 8-8-8h-2L14 22v2l8 8-8 8L4 30zm48 8L38 40H26L16 30l8-8 8 8h2l8-8v-2l-8-8 8-8 10 10z" transform="translate(0 6)"/>'},
{id:'fold', name:'Aperture', family:'A cut-paper tile', note:'An asymmetric square folds around an open center. A single diagonal cut gives the mark direction without an arrow, robot, or sparkle.', tradeoff:'The most abstract and artistic candidate. Its relationship to Mosaic will rely on repeated use with the wordmark.', paths:'<path fill-rule="evenodd" d="M4 4h30v10H14v28H4zm34 0 14 14v34H18V18h16v10h-6v14h14V22l-4-4z"/>'},
];
const icons = {
home:'<path d="m3 10 9-7 9 7v10H3zM9 20v-7h6v7"/>',
conversation:'<path d="M4 4h16v12H9l-5 4zM8 8h8M8 12h5"/>',
projects:'<path d="M3 6h7l2 3h9v11H3zM3 6V4h7l2 2h7v3"/>',
agents:'<rect x="5" y="7" width="14" height="13" rx="3"/><path d="M12 3v4M9 12h.01M15 12h.01M9 16h6M2 11v5M22 11v5"/>',
people:'<circle cx="9" cy="7" r="3"/><path d="M3 21v-3a6 6 0 0 1 12 0v3M16 4a3 3 0 0 1 0 6M18 14a5 5 0 0 1 3 4v3"/>',
board:'<rect x="3" y="3" width="18" height="18" rx="2"/><path d="M9 3v18M15 3v18M6 7v4M12 7v7M18 7v2"/>',
extensions:'<rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/><path d="M14 17.5h7M17.5 14v7"/>',
search:'<circle cx="10" cy="10" r="6"/><path d="m15 15 6 6"/>',
check:'<path d="m5 12 4 4L19 6"/>',
warning:'<path d="m12 3 10 18H2zM12 9v5M12 17h.01"/>',
error:'<circle cx="12" cy="12" r="9"/><path d="m9 9 6 6m0-6-6 6"/>',
plus:'<path d="M12 4v16M4 12h16"/>',
arrow:'<path d="M4 12h16m-6-6 6 6-6 6"/>',
sun:'<circle cx="12" cy="12" r="4"/><path d="M12 2v2m0 16v2M2 12h2m16 0h2M5 5l1 1m12 12 1 1M5 19l1-1M18 6l1-1"/>',
dim:'<circle cx="12" cy="12" r="9"/><path d="M12 3v18M12 7h6M12 12h9M12 17h6"/>',
moon:'<path d="M20 14A9 9 0 0 1 10 3a9 9 0 1 0 10 11z"/>',
};
function hsl(h,s,l) {
s/=100; l/=100;
const c=(1-Math.abs(2*l-1))*s, x=c*(1-Math.abs(h/60%2-1)), m=l-c/2;
const rgb=h<60?[c,x,0]:h<120?[x,c,0]:h<180?[0,c,x]:h<240?[0,x,c]:h<300?[x,0,c]:[c,0,x];
return '#'+rgb.map(v=>Math.round((v+m)*255).toString(16).padStart(2,'0')).join('');
}
function luminance(hex) {
const a=hex.slice(1).match(/../g).map(x=>parseInt(x,16)/255).map(v=>v<=0.04045?v/12.92:((v+0.055)/1.055)**2.4);
return a[0]*.2126+a[1]*.7152+a[2]*.0722;
}
function contrast(a,b) { const x=luminance(a), y=luminance(b);return (Math.max(x,y)+.05)/(Math.min(x,y)+.05); }
function foreground(h,s,start, backgrounds, minimum, light) {
for(let l=start; l>=0 && l<=100; l+=light?-1:1) {
const c=hsl(h,s,l);
if(backgrounds.every(bg=>contrast(c,bg)>=minimum)) return c;
}
throw new Error('No contrast-compliant color');
}
function tokens(p, mode) {
const light=mode==='light', dim=mode==='dim', s=Math.min(p.sat*.3,22);
const canvas=hsl(p.hue,s,light?96:dim?18:9);
const surface=light?'#ffffff':hsl(p.hue,s,dim?23:14);
const raised=hsl(p.hue,s,light?92:dim?28:20);
const backgrounds=[canvas,surface,raised];
const color=(h,s,min=4.5)=>foreground(h,s,light?44:68,backgrounds,min,light);
const action=color(p.hue,p.sat);
const onAction=contrast('#ffffff',action)>=4.5?'#ffffff':'#10141a';
return {canvas,surface,raised,text:color(p.hue,15,7),muted:color(p.hue,12),
line:hsl(p.hue,s,light?84:dim?35:28),border:color(p.hue,12,3),action,onAction,
accent:color(p.accent,p.accentSat),focus:action,success:color(157,49),warning:color(34,70),danger:color(3,66)};
}
function logo(id, size=56) {const l=logos.find(l=>l.id===id)||logos[0];return `<svg class="logo" width="${size}" height="${size}" viewBox="0 0 56 56" fill="currentColor" aria-hidden="true">${l.paths}</svg>`;}
function icon(id) {return `<svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${icons[id]||icons.home}</svg>`;}
root.Brand = {palettes,fonts,logos,icons,tokens,contrast,logo,icon};
})(typeof window === 'undefined' ? globalThis : window);
+10
View File
@@ -0,0 +1,10 @@
import '../brand.js';
import {mkdir,writeFile} from 'node:fs/promises';
const out=new URL('../assets/logos/',import.meta.url);
await mkdir(out,{recursive:true});
for(const l of Brand.logos){
await writeFile(new URL(`${l.name.toLowerCase()}.svg`,out),`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 56 56" fill="#215fac" role="img" aria-label="Mosaic Stack ${l.name} concept">${l.paths}</svg>\n`);
}
const palettes=Brand.palettes.map(p=>({...p,modes:Object.fromEntries(['light','dim','dark'].map(m=>[m,Brand.tokens(p,m)]))}));
await writeFile(new URL('../assets/palettes.json',import.meta.url),JSON.stringify({prototype:true,palettes},null,2)+'\n');
console.log('Generated 3 original SVG assets and 30 palette/mode token sets.');
+78
View File
@@ -0,0 +1,78 @@
// Small CDP client for the installed Chromium. No application dependencies.
import { spawn } from 'node:child_process';
import { mkdtemp, rm, writeFile } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
export async function browser() {
const profile = await mkdtemp(join(tmpdir(), 'dewey-brand-browser-'));
const child = spawn(process.env.CHROMIUM || '/usr/bin/chromium', [
'--headless', '--no-first-run', '--no-default-browser-check',
'--disable-dev-shm-usage', '--remote-debugging-pipe', `--user-data-dir=${profile}`,
], { stdio: ['ignore', 'ignore', 'ignore', 'pipe', 'pipe'] });
let id = 0, buffer = '';
const pending = new Map();
child.stdio[4].on('data', chunk => {
buffer += chunk.toString();
let end;
while ((end = buffer.indexOf('\0')) !== -1) {
const message = JSON.parse(buffer.slice(0, end));
buffer = buffer.slice(end + 1);
if (pending.has(message.id)) {
const { resolve, reject, timeout } = pending.get(message.id);
clearTimeout(timeout);
pending.delete(message.id);
message.error ? reject(new Error(JSON.stringify(message.error))) : resolve(message.result);
}
}
});
function send(method, params = {}, sessionId) {
return new Promise((resolve, reject) => {
const key = ++id;
const timeout = setTimeout(() => { pending.delete(key); reject(new Error(`CDP timeout: ${method}`)); }, 25000);
pending.set(key, { resolve, reject, timeout });
child.stdio[3].write(JSON.stringify({ id: key, method, params, ...(sessionId ? {sessionId} : {}) }) + '\0');
});
}
const { targetId } = await send('Target.createTarget', { url: 'about:blank' });
const { sessionId } = await send('Target.attachToTarget', { targetId, flatten: true });
const call = (method, params) => send(method, params, sessionId);
await call('Page.enable');
await call('Runtime.enable');
const evaluate = async expression => {
const r = await call('Runtime.evaluate', { expression, returnByValue: true, awaitPromise: true });
if (r.exceptionDetails) throw new Error(r.exceptionDetails.text + ': ' + r.result.description);
return r.result.value;
};
return {
call, evaluate,
async viewport(width, height = 1000) {
await call('Emulation.setDeviceMetricsOverride', { width, height, deviceScaleFactor: 1, mobile: false });
},
async navigate(url) {
const result = await call('Page.navigate', { url });
if (result.errorText) throw new Error(result.errorText);
// Bounded page-load check, not an agent wake/watch loop.
for (let n = 0; n < 50; n++) {
if (await evaluate('document.readyState === "complete"')) break;
await new Promise(r => setTimeout(r, 100));
}
await evaluate('document.fonts.ready.then(() => true)');
return result;
},
async screenshot(path) {
const { data } = await call('Page.captureScreenshot', { format: 'png' });
await writeFile(path, Buffer.from(data, 'base64'));
},
async key(key, code = key, modifiers = 0) {
const virtual = { Tab: 9, Enter: 13, Escape: 27, ArrowDown: 40, ArrowRight: 39, ' ': 32 }[key];
await call('Input.dispatchKeyEvent', { type: 'keyDown', key, code, modifiers, windowsVirtualKeyCode: virtual, text: key === 'Enter' ? '\r' : key.length === 1 ? key : '' });
await call('Input.dispatchKeyEvent', { type: 'keyUp', key, code, modifiers, windowsVirtualKeyCode: virtual });
},
async close() {
await send('Browser.close').catch(() => {});
if (child.exitCode === null) await new Promise(resolve => child.once('exit', resolve));
await rm(profile, { recursive: true, force: true });
},
};
}
@@ -0,0 +1,92 @@
import {browser} from './browser.mjs';
import {mkdir,writeFile,readFile} from 'node:fs/promises';
import {fileURLToPath} from 'node:url';
import assert from 'node:assert/strict';
const out=new URL('../evidence/',import.meta.url), downloads=new URL('downloads/',out);
await mkdir(downloads,{recursive:true});
const report={observedAt:new Date().toISOString(),checks:[],renderedContrast:[]};
const b=await browser();
const url=new URL('../index.html',import.meta.url).href;
const change=async(id,value)=>b.evaluate(`(()=>{const e=document.getElementById(${JSON.stringify(id)});e.value=${JSON.stringify(value)};e.dispatchEvent(new Event('change',{bubbles:true}))})()`);
const mode=async value=>b.evaluate(`document.querySelector('[name=mode][value=${value}]').click()`);
const screenshot=async(section,name,width=1440)=>{
await b.viewport(width,1100);
await b.evaluate(`document.getElementById('${section}').scrollIntoView();new Promise(requestAnimationFrame)`);
await b.screenshot(new URL(name,out));
};
try{
await b.viewport(1440,1100);await b.navigate(url);
// Computed foreground/background values on rendered text, not just token formulas.
for(const p of await b.evaluate('Brand.palettes.map(p=>p.id)')) for(const m of ['light','dim','dark']){
await change('palette',p);await mode(m);
const result=await b.evaluate(`(()=>{
const hex=c=>{const n=c.match(/[\\d.]+/g);return '#'+n.slice(0,3).map(v=>Math.round(+v).toString(16).padStart(2,'0')).join('')};
const bg=e=>{for(let n=e;n;n=n.parentElement){const c=getComputedStyle(n).backgroundColor;if(c!=='rgba(0, 0, 0, 0)'&&c!=='transparent')return hex(c)}return '#ffffff'};
const walker=document.createTreeWalker(document.body,NodeFilter.SHOW_TEXT);let n, checks=[];
while(n=walker.nextNode()){
const e=n.parentElement;if(!n.textContent.trim()||e.closest('script,style,noscript,.sr-only,button:disabled,option'))continue;
const rect=e.getBoundingClientRect();if(!rect.width||!rect.height)continue;
const style=getComputedStyle(e);if(style.visibility==='hidden'||style.display==='none')continue;
const fg=hex(style.color),back=bg(e),ratio=Brand.contrast(fg,back);
const large=parseFloat(style.fontSize)>=24||(parseFloat(style.fontSize)>=18.67 && parseFloat(style.fontWeight)>=700);
checks.push({text:n.textContent.trim().slice(0,65),fg,bg:back,ratio,minimum:large?3:4.5});
}
for(const e of document.querySelectorAll('input:not([type=radio]),textarea,select')){
const style=getComputedStyle(e),fg=hex(style.color),back=bg(e);checks.push({text:e.id,fg,bg:back,ratio:Brand.contrast(fg,back),minimum:4.5});
}
return {count:checks.length,min:Math.min(...checks.map(x=>x.ratio)),failures:checks.filter(x=>x.ratio<x.minimum)};
})()`);
report.renderedContrast.push({palette:p,mode:m,...result});
assert.equal(result.failures.length,0,JSON.stringify({p,m,...result}));
}
report.checks.push({name:'Computed rendered text contrast across 30 combinations',result:'pass'});
await change('palette','harbor');await mode('light');
for(const section of ['identity','typography','color','components','review'])await screenshot(section,`section-${section}-light.png`);
await screenshot('color','section-color-ultrawide.png',3440);
await screenshot('identity','section-identity-mobile.png',390);
await screenshot('components','section-components-mobile.png',320);
await mode('dark');await screenshot('color','section-color-dark.png');
await mode('light');await b.viewport(1440,768);
await b.evaluate('document.getElementById("reset").focus()');await b.key('Tab','Tab',8);
const focus=await b.evaluate(`(()=>{const e=document.activeElement,r=e.getBoundingClientRect();return {text:e.textContent,top:r.top,bottom:r.bottom,viewport:innerHeight,style:getComputedStyle(e).outlineStyle}})()`);
assert(focus.top>=0&&focus.bottom<=focus.viewport,JSON.stringify(focus));
await b.screenshot(new URL('focus-short-desktop.png',out));
report.checks.push({name:'Sidebar keyboard focus visible at 768 px viewport height',result:'pass',focus});
const ax=await b.call('Accessibility.getFullAXTree');
const missingNames=ax.nodes.filter(n=>!n.ignored&&['button','combobox','textbox','radio','link'].includes(n.role?.value)&&!n.name?.value);
assert.equal(missingNames.length,0);
report.checks.push({name:'Chromium accessibility tree gives interactive elements accessible names',result:'pass',namedControls:ax.nodes.filter(n=>!n.ignored&&['button','combobox','textbox','radio','link'].includes(n.role?.value)).length});
await b.call('Browser.setDownloadBehavior',{behavior:'allow',downloadPath:fileURLToPath(downloads)});
await b.evaluate('document.getElementById("review-notes").value="Prefer Relay. Please refine the small-size gaps.";document.getElementById("download-review").click();document.getElementById("export").click()');
// Wait only for these two local browser downloads, bounded at five seconds.
let saved;
for(let n=0;n<50;n++){
try{saved=[await readFile(new URL('mosaic-brand-review.txt',downloads),'utf8'),await readFile(new URL('mosaic-harbor-tokens.json',downloads),'utf8')];break;}catch{await new Promise(r=>setTimeout(r,100));}
}
assert(saved,'Local downloads did not complete');
assert(saved[0].includes('Prefer Relay.'));
assert.deepEqual(Object.keys(JSON.parse(saved[1]).modes),['light','dim','dark']);
report.checks.push({name:'Review notes and all-three-mode palette JSON downloaded and content-verified',result:'pass'});
// Double every computed text size, including authored pixel sizes.
await b.viewport(320,1000);
await b.evaluate(`(()=>{const sizes=[...document.querySelectorAll('body *')].map(e=>[e,parseFloat(getComputedStyle(e).fontSize)]);for(const[e,size]of sizes)e.style.fontSize=size*2+'px'})()`);
let expanded=await b.evaluate('({width:innerWidth,scroll:document.documentElement.scrollWidth})');
assert(expanded.scroll<=expanded.width,JSON.stringify(expanded));
await b.screenshot(new URL('board-all-text-200-320.png',out));
report.checks.push({name:'Every computed text size doubled at 320 px',result:'pass',measurement:expanded});
// Font failure and storage denial are injected only into this isolated test browser.
await b.call('Network.enable');await b.call('Network.setCacheDisabled',{cacheDisabled:true});
await b.call('Network.setBlockedURLs',{urls:['*woff2*']});
await b.call('Page.addScriptToEvaluateOnNewDocument',{source:'Object.defineProperty(window,"localStorage",{get(){throw new DOMException("Unavailable","SecurityError")}})'});
await b.navigate(url);await change('palette','carmine');await mode('dim');
assert.equal(await b.evaluate('document.documentElement.dataset.palette'),'carmine');
expanded=await b.evaluate('({width:innerWidth,scroll:document.documentElement.scrollWidth})');
assert(expanded.scroll<=expanded.width,JSON.stringify(expanded));
assert(!(await b.evaluate('document.fonts.check(\'16px "DM Sans"\')')));
await b.screenshot(new URL('board-font-storage-fallback-320.png',out));
report.checks.push({name:'Blocked fonts and denied storage: controls still work and fallback reflows',result:'pass',measurement:expanded});
}catch(error){report.failure=error.stack;}
finally{await b.close();}
await writeFile(new URL('detail-verification.json',out),JSON.stringify(report,null,2)+'\n');
console.log(JSON.stringify(report,null,2));
if(report.failure)process.exitCode=1;
@@ -0,0 +1,31 @@
"""Fetch public font assets and OFL licenses. Run only when refreshing assets."""
from pathlib import Path
import urllib.request
import re
out = Path(__file__).resolve().parent.parent / 'assets' / 'fonts'
out.mkdir(parents=True, exist_ok=True)
fonts = [('DM Sans', 'dm-sans', 'dmsans'), ('IBM Plex Sans', 'ibm-plex-sans', 'ibmplexsans'), ('Manrope', 'manrope', 'manrope')]
for family, slug, upstream in fonts:
url = 'https://fonts.googleapis.com/css2?family=' + family.replace(' ', '+') + ':wght@400;500;600;700&display=swap'
req = urllib.request.Request(url, headers={'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36'})
css = urllib.request.urlopen(req, timeout=25).read().decode()
# Google returns one Latin block per requested weight. Keep all four real weights.
sources = []
for weight in ['400','500','600','700']:
blocks = re.findall(r'/\* latin \*/\s*(@font-face\s*\{[^}]+\})', css)
block = next((b for b in blocks if f'font-weight: {weight};' in b), None)
if not block:
raise RuntimeError(f'No Latin block for {family} {weight}')
source = re.search(r'url\(([^)]+)\)', block).group(1)
data = urllib.request.urlopen(source, timeout=25).read()
assert data[:4] == b'wOF2', 'Expected WOFF2'
name = f'{slug}-{weight}.woff2'
(out / name).write_bytes(data)
sources.append(f'{weight}: {source}')
license_url = f'https://raw.githubusercontent.com/google/fonts/main/ofl/{upstream}/OFL.txt'
license_text = urllib.request.urlopen(license_url, timeout=25).read()
assert b'SIL OPEN FONT LICENSE' in license_text
(out / f'{slug}-OFL.txt').write_bytes(license_text)
(out / f'{slug}-sources.txt').write_text(f'{family}\nCSS: {url}\nLicense: {license_url}\n' + '\n'.join(sources) + '\n')
print(f'{family}: 4 WOFF2 weights and OFL license saved')
@@ -0,0 +1,41 @@
import {browser} from './browser.mjs';
import {writeFile,readFile,stat} from 'node:fs/promises';
import assert from 'node:assert/strict';
const b=await browser(), report={observedAt:new Date().toISOString(),checks:[]};
const url=new URL('../index.html',import.meta.url);
try{
await b.viewport(1440,900);await b.navigate(url.href);
const resources=(await b.call('Page.getResourceTree')).frameTree.resources.map(x=>x.url);
assert(resources.length>5);assert(resources.every(u=>u.startsWith('file:')));
report.checks.push({name:'Entry page loads only local resources',result:'pass',resourceCount:resources.length});
const links=await b.evaluate('[...document.querySelectorAll("a[href],link[href],script[src]")].map(x=>x.getAttribute("href")||x.getAttribute("src"))');
for(const link of links){
if(link.startsWith('#'))assert(await b.evaluate(`!!document.getElementById(${JSON.stringify(link.slice(1))})`),link);
else assert((await stat(new URL(link,url))).isFile(),link);
}
const css=await readFile(new URL('../styles.css',import.meta.url),'utf8');
for(const match of css.matchAll(/url\('([^']+)'\)/g))assert((await stat(new URL(match[1],url))).isFile());
report.checks.push({name:'HTML and CSS asset links and in-page anchors resolve',result:'pass'});
await b.evaluate('document.querySelector(".skip").focus()');await b.key('Enter');
assert.equal(await b.evaluate('document.activeElement.id'),'main');
report.checks.push({name:'Keyboard skip link moves focus to main',result:'pass'});
for(const width of [699,700,959,960,1199,1200,1699,1700,2399,2400]){
await b.viewport(width,900);
assert(await b.evaluate('document.documentElement.scrollWidth<=innerWidth'),String(width));
}
report.checks.push({name:'Both sides of five responsive breakpoints have no page overflow',result:'pass',widths:[699,700,959,960,1199,1200,1699,1700,2399,2400]});
for(const width of [320,1440]){
await b.viewport(width,900);
const small=await b.evaluate(`([...document.querySelectorAll('button,input,select,textarea,.controls nav a,.brand-home,.review-link')].filter(e=>!e.disabled).map(e=>{const r=e.getBoundingClientRect();return {id:e.id||e.textContent.trim().slice(0,30),width:r.width,height:r.height}}).filter(r=>r.width<24||r.height<24))`);
assert.deepEqual(small,[]);
}
report.checks.push({name:'Interactive control targets meet 24 px at 320 and 1440 widths',result:'pass',qualification:'Inline prose/footer links use the WCAG inline-text exception.'});
await b.evaluate('localStorage.setItem("mosaic-brand-preview-v1", "{broken JSON");');
await b.navigate(url.href);
assert.equal(await b.evaluate('document.documentElement.dataset.palette'),'harbor');
report.checks.push({name:'Malformed preference storage recovers to a usable default',result:'pass'});
}catch(error){report.failure=error.stack;}
finally{await b.close();}
await writeFile(new URL('../evidence/final-verification.json',import.meta.url),JSON.stringify(report,null,2)+'\n');
console.log(JSON.stringify(report,null,2));
if(report.failure)process.exitCode=1;
@@ -0,0 +1,34 @@
import { browser } from './browser.mjs';
import { mkdir, writeFile } from 'node:fs/promises';
const out = new URL('../evidence/', import.meta.url);
await mkdir(out, {recursive: true});
const b = await browser();
const results = [];
try {
for (const [name, url] of [['t3','https://t3.codes/'], ['buzz','https://buzz.xyz/']]) {
const entry = {name, url, observedAt: new Date().toISOString()};
try {
await b.viewport(1440, 1100);
await b.navigate(url);
// Allow the reference sites' entrance animation to finish before capture.
await new Promise(resolve => setTimeout(resolve, 4000));
entry.desktop = await b.evaluate(`({title:document.title, url:location.href,
headings:[...document.querySelectorAll('h1,h2,h3')].map(x=>x.textContent.trim()).slice(0,25),
controls:[...document.querySelectorAll('button,a,input')].map(x=>({tag:x.tagName,text:(x.textContent||x.getAttribute('aria-label')||x.placeholder||'').trim().slice(0,100),href:x.getAttribute('href')})).filter(x=>x.text).slice(0,65),
body:{font:getComputedStyle(document.body).fontFamily,bg:getComputedStyle(document.body).backgroundColor,color:getComputedStyle(document.body).color},
text:document.body.innerText.slice(0,6500)})`);
await b.screenshot(new URL(`${name}-desktop.png`, out));
await b.evaluate('window.scrollTo(0, 1500)');
await new Promise(resolve => setTimeout(resolve, 700));
await b.screenshot(new URL(`${name}-details.png`, out));
await b.evaluate('window.scrollTo(0, 0)');
await b.viewport(390, 844);
await new Promise(resolve => setTimeout(resolve, 700));
await b.screenshot(new URL(`${name}-mobile.png`, out));
entry.mobile = await b.evaluate('({width:innerWidth,scrollWidth:document.documentElement.scrollWidth})');
} catch(error) {entry.error = error.message;}
results.push(entry);
}
} finally {await b.close();}
await writeFile(new URL('references.json', out), JSON.stringify(results, null, 2));
console.log(results.map(x=>({name:x.name,title:x.desktop?.title,error:x.error,mobile:x.mobile})));
+106
View File
@@ -0,0 +1,106 @@
import '../brand.js';
import {browser} from './browser.mjs';
import {mkdir,writeFile} from 'node:fs/promises';
import assert from 'node:assert/strict';
const out=new URL('../evidence/',import.meta.url);
await mkdir(out,{recursive:true});
const report={observedAt:new Date().toISOString(),browser:'Installed headless Chromium through CDP',contrast:[],layouts:[],interactions:[],limits:['No Firefox, Safari, real mobile device, screen reader, or trademark clearance.']};
for(const p of Brand.palettes)for(const mode of ['light','dim','dark']){
const t=Brand.tokens(p,mode),checks=[];
for(const fg of ['text','muted','action','accent','success','warning','danger'])for(const bg of ['canvas','surface','raised'])checks.push({fg,bg,minimum:4.5,ratio:Brand.contrast(t[fg],t[bg])});
for(const fg of ['border','focus'])for(const bg of ['canvas','surface','raised'])checks.push({fg,bg,minimum:3,ratio:Brand.contrast(t[fg],t[bg])});
checks.push({fg:'onAction',bg:'action',minimum:4.5,ratio:Brand.contrast(t.onAction,t.action)});
assert(checks.every(c=>c.ratio>=c.minimum),`${p.id}/${mode} contrast`);
report.contrast.push({palette:p.id,mode,checks});
}
const b=await browser();
const url=new URL('../index.html',import.meta.url).href;
const change=async(id,value)=>b.evaluate(`(()=>{const e=document.getElementById(${JSON.stringify(id)});e.value=${JSON.stringify(value)};e.dispatchEvent(new Event('change',{bubbles:true}));return e.value})()`);
const mode=async value=>b.evaluate(`document.querySelector('[name="mode"][value="${value}"]').click()`);
const measure=()=>b.evaluate(`({width:innerWidth,scroll:document.documentElement.scrollWidth,body:document.body.scrollWidth,overflows:[...document.querySelectorAll('main *,header *,aside *')].filter(e=>{const r=e.getBoundingClientRect();return r.width>0&&(r.right>innerWidth+1||r.left < -1)&&!e.classList.contains('sr-only')}).slice(0,10).map(e=>({tag:e.tagName,class:e.className,id:e.id}))})`);
try{
await b.call('Page.addScriptToEvaluateOnNewDocument',{source:'window.__errors=[];addEventListener("error",e=>window.__errors.push(e.message));addEventListener("unhandledrejection",e=>window.__errors.push(String(e.reason)));'});
await b.viewport(1440,1100);
await b.navigate(url);
assert.equal(await b.evaluate('document.querySelectorAll("[data-palette-card]").length'),10);
assert.equal(await b.evaluate('document.querySelectorAll("[data-mark-card]").length'),3);
assert.equal(await b.evaluate('document.querySelectorAll("[data-font-card]").length'),3);
// All theme choices are applied through the actual page controls, then laid out.
for(const p of Brand.palettes)for(const m of ['light','dim','dark']){
await change('palette',p.id);await mode(m);
assert.equal(await b.evaluate('document.documentElement.dataset.palette'),p.id);
assert.equal(await b.evaluate('document.documentElement.dataset.mode'),m);
for(const width of [320,390,768,960,1440,1920,2560,3440]){
await b.viewport(width,1000);
const result=await measure();
report.layouts.push({palette:p.id,mode:m,...result});
assert(result.scroll<=width && result.body<=width && !result.overflows.length,JSON.stringify(report.layouts.at(-1)));
}
}
await change('palette','harbor');await mode('light');
for(const width of [320,390,768,1440,3440]){
await b.viewport(width,width===390?844:1100);await b.evaluate('scrollTo(0,0)');
await b.screenshot(new URL(`board-light-${width}.png`,out));
}
for(const m of ['dim','dark']){
await mode(m);await b.viewport(1440,1100);await b.evaluate('scrollTo(0,0)');
await b.screenshot(new URL(`board-${m}-1440.png`,out));
}
// Real keyboard: native select, radio navigation, buttons, forward/reverse tab.
await mode('light');await b.viewport(1440,1100);
await b.evaluate('document.getElementById("palette").focus()');
await b.key('ArrowDown');await b.key('Enter');
assert.equal(await b.evaluate('document.getElementById("palette").value'),'carmine');
await b.evaluate('document.querySelector("[name=mode][value=light]").focus()');
await b.key('ArrowRight');
assert.equal(await b.evaluate('document.documentElement.dataset.mode'),'dim');
const focus=await b.evaluate('({outline:getComputedStyle(document.activeElement.nextElementSibling).outlineStyle,width:getComputedStyle(document.activeElement.nextElementSibling).outlineWidth})');
assert.equal(focus.outline,'solid');assert.equal(focus.width,'3px');
await b.evaluate('document.querySelector("[data-choose-mark=weave]").focus()');await b.key('Enter');
assert.equal(await b.evaluate('document.getElementById("mark").value'),'weave');
await b.evaluate('document.querySelector("[data-choose-font=plex]").focus()');await b.key(' ' ,'Space');
assert.equal(await b.evaluate('document.getElementById("font").value'),'plex');
await b.evaluate('document.getElementById("sample-title").focus()');
await b.key('Tab');assert.equal(await b.evaluate('document.activeElement.id'),'sample-state');
await b.key('Tab','Tab',8);assert.equal(await b.evaluate('document.activeElement.id'),'sample-title');
report.interactions.push({name:'Keyboard selection, native radio arrow, Enter/Space buttons, Tab/Shift+Tab',result:'pass',focus});
await change('sample-state','error');
assert.equal(await b.evaluate('document.getElementById("sample-title").value'),'Summer reading notes');
await b.evaluate('document.getElementById("sample-action").focus()');await b.key('Enter');
assert.equal(await b.evaluate('document.getElementById("sample-feedback").dataset.state'),'success');
await change('sample-state','loading');assert(await b.evaluate('document.getElementById("sample-action").disabled'));
for(const s of ['empty','ready']) {await change('sample-state',s);assert.equal(await b.evaluate('document.getElementById("sample-feedback").dataset.state'),s);}
report.interactions.push({name:'All five component states and error recovery preserving input',result:'pass'});
// All bundled families loaded, and long labels remain usable at mobile width.
for(const f of Brand.fonts){
await change('font',f.id);await b.evaluate('document.fonts.ready.then(()=>true)');
const loaded=await b.evaluate(`document.fonts.check('16px "${f.name}"')`);
assert(loaded,f.name+' font load');
await b.viewport(320,1000);assert((await measure()).scroll<=320);
}
report.interactions.push({name:'Three local fonts loaded and reflowed at 320 px',result:'pass'});
await b.evaluate('document.getElementById("review-notes").value="Keep this review note.";document.getElementById("review-notes").dispatchEvent(new Event("input"));document.getElementById("reset").click()');
assert.equal(await b.evaluate('document.getElementById("review-notes").value'),'Keep this review note.');
await b.navigate(url);
assert.equal(await b.evaluate('document.getElementById("review-notes").value'),'Keep this review note.');
report.interactions.push({name:'Local preference and note storage; reset preserves notes',result:'pass'});
await b.call('Emulation.setEmulatedMedia',{features:[{name:'prefers-reduced-motion',value:'reduce'}]});
await mode('dark');await b.key('Tab');
assert(await b.evaluate('matchMedia("(prefers-reduced-motion: reduce)").matches'));
report.interactions.push({name:'Reduced motion still permits theme and keyboard interaction',result:'pass'});
await b.viewport(320,1000);
await b.evaluate(`(()=>{const style=document.createElement('style');style.id='spacing-test';style.textContent='*{line-height:1.5!important;letter-spacing:.12em!important;word-spacing:.16em!important}p{margin-bottom:2em!important}';document.head.append(style)})()`);
let result=await measure();assert(result.scroll<=320,JSON.stringify(result));
await b.screenshot(new URL('board-text-spacing-320.png',out));
await b.evaluate('document.getElementById("spacing-test").remove();document.documentElement.style.fontSize="200%"');
result=await measure();assert(result.scroll<=320,JSON.stringify(result));
await b.screenshot(new URL('board-text-200-320.png',out));
report.interactions.push({name:'320 px text-spacing overrides and root text size 200%',result:'pass',qualification:'Not browser-native zoom; pixel-sized component text also needs separate scaling checks.'});
await b.evaluate('document.documentElement.style.fontSize=""');
const errors=await b.evaluate('window.__errors');assert.deepEqual(errors,[]);
report.interactions.push({name:'Uncaught page errors',result:'pass',errors});
} catch(error){report.failure=error.stack;}
finally{await b.close();}
await writeFile(new URL('verification.json',out),JSON.stringify(report,null,2)+'\n');
console.log(JSON.stringify({contrastSets:report.contrast.length,layouts:report.layouts.length,interactions:report.interactions,failure:report.failure},null,2));
if(report.failure)process.exitCode=1;
Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

@@ -0,0 +1,257 @@
{
"observedAt": "2026-09-08T13:49:13.216Z",
"checks": [
{
"name": "Computed rendered text contrast across 30 combinations",
"result": "pass"
},
{
"name": "Sidebar keyboard focus visible at 768 px viewport height",
"result": "pass",
"focus": {
"text": "05 Your review",
"top": 630.109375,
"bottom": 674.109375,
"viewport": 768,
"style": "solid"
}
},
{
"name": "Chromium accessibility tree gives interactive elements accessible names",
"result": "pass",
"namedControls": 60
},
{
"name": "Review notes and all-three-mode palette JSON downloaded and content-verified",
"result": "pass"
},
{
"name": "Every computed text size doubled at 320 px",
"result": "pass",
"measurement": {
"width": 320,
"scroll": 305
}
},
{
"name": "Blocked fonts and denied storage: controls still work and fallback reflows",
"result": "pass",
"measurement": {
"width": 320,
"scroll": 305
}
}
],
"renderedContrast": [
{
"palette": "harbor",
"mode": "light",
"count": 274,
"min": 4.612829123046221,
"failures": []
},
{
"palette": "harbor",
"mode": "dim",
"count": 274,
"min": 4.504658476260286,
"failures": []
},
{
"palette": "harbor",
"mode": "dark",
"count": 274,
"min": 5.167615908293434,
"failures": []
},
{
"palette": "carmine",
"mode": "light",
"count": 274,
"min": 4.662315521062682,
"failures": []
},
{
"palette": "carmine",
"mode": "dim",
"count": 274,
"min": 4.587463027691096,
"failures": []
},
{
"palette": "carmine",
"mode": "dark",
"count": 274,
"min": 4.695553088417374,
"failures": []
},
{
"palette": "atlantic",
"mode": "light",
"count": 274,
"min": 4.515881820137726,
"failures": []
},
{
"palette": "atlantic",
"mode": "dim",
"count": 274,
"min": 4.516521277596746,
"failures": []
},
{
"palette": "atlantic",
"mode": "dark",
"count": 274,
"min": 5.597708271207925,
"failures": []
},
{
"palette": "terracotta",
"mode": "light",
"count": 274,
"min": 4.518475634580629,
"failures": []
},
{
"palette": "terracotta",
"mode": "dim",
"count": 274,
"min": 4.538542941476706,
"failures": []
},
{
"palette": "terracotta",
"mode": "dark",
"count": 274,
"min": 5.525894813496129,
"failures": []
},
{
"palette": "aubergine",
"mode": "light",
"count": 274,
"min": 4.664757683683436,
"failures": []
},
{
"palette": "aubergine",
"mode": "dim",
"count": 274,
"min": 4.560324571031366,
"failures": []
},
{
"palette": "aubergine",
"mode": "dark",
"count": 274,
"min": 4.999968974923534,
"failures": []
},
{
"palette": "mineral",
"mode": "light",
"count": 274,
"min": 4.549690583339469,
"failures": []
},
{
"palette": "mineral",
"mode": "dim",
"count": 274,
"min": 4.575057699689022,
"failures": []
},
{
"palette": "mineral",
"mode": "dark",
"count": 274,
"min": 5.6577550779736105,
"failures": []
},
{
"palette": "cobalt",
"mode": "light",
"count": 274,
"min": 4.706276899711153,
"failures": []
},
{
"palette": "cobalt",
"mode": "dim",
"count": 274,
"min": 4.5100156460147796,
"failures": []
},
{
"palette": "cobalt",
"mode": "dark",
"count": 274,
"min": 4.534974293870712,
"failures": []
},
{
"palette": "rosewood",
"mode": "light",
"count": 274,
"min": 4.636598241711077,
"failures": []
},
{
"palette": "rosewood",
"mode": "dim",
"count": 274,
"min": 4.584411037938534,
"failures": []
},
{
"palette": "rosewood",
"mode": "dark",
"count": 274,
"min": 4.964802403187582,
"failures": []
},
{
"palette": "graphite",
"mode": "light",
"count": 274,
"min": 4.613910901400341,
"failures": []
},
{
"palette": "graphite",
"mode": "dim",
"count": 274,
"min": 4.565616755282305,
"failures": []
},
{
"palette": "graphite",
"mode": "dark",
"count": 274,
"min": 5.478526170936041,
"failures": []
},
{
"palette": "grove",
"mode": "light",
"count": 274,
"min": 4.52023260851089,
"failures": []
},
{
"palette": "grove",
"mode": "dim",
"count": 274,
"min": 4.564633732635816,
"failures": []
},
{
"palette": "grove",
"mode": "dark",
"count": 274,
"min": 5.707548102674204,
"failures": []
}
]
}
@@ -0,0 +1,43 @@
{
"observedAt": "2026-09-08T13:52:02.918Z",
"checks": [
{
"name": "Entry page loads only local resources",
"result": "pass",
"resourceCount": 11
},
{
"name": "HTML and CSS asset links and in-page anchors resolve",
"result": "pass"
},
{
"name": "Keyboard skip link moves focus to main",
"result": "pass"
},
{
"name": "Both sides of five responsive breakpoints have no page overflow",
"result": "pass",
"widths": [
699,
700,
959,
960,
1199,
1200,
1699,
1700,
2399,
2400
]
},
{
"name": "Interactive control targets meet 24 px at 320 and 1440 widths",
"result": "pass",
"qualification": "Inline prose/footer links use the WCAG inline-text exception."
},
{
"name": "Malformed preference storage recovers to a usable default",
"result": "pass"
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 222 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 KiB

File diff suppressed because it is too large Load Diff
+111
View File
@@ -0,0 +1,111 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="color-scheme" content="light dark">
<meta name="description" content="Mosaic Stack brand studies. A local, interactive review of identity, type, and color. Not a working product.">
<title>Mosaic Stack · Brand studies</title>
<link rel="icon" href="assets/logos/assembly.svg" type="image/svg+xml">
<link rel="stylesheet" href="styles.css">
<script src="brand.js" defer></script>
<script src="board.js" defer></script>
</head>
<body>
<a class="skip" href="#main">Skip to brand studies</a>
<header class="masthead">
<a class="brand-home" href="#top" aria-label="Mosaic Stack brand board, top"><span data-logo></span><span>Mosaic Stack</span></a>
<div class="masthead-note">Brand studies <span class="edition">01 / for discussion</span></div>
<a href="#review" class="review-link">Review guide <span aria-hidden="true"></span></a>
</header>
<div id="top" class="layout">
<aside class="controls" aria-label="Brand preview controls">
<div class="control-inner">
<p class="eyebrow">Make it yours</p>
<p class="control-intro">Change the palette, not the product.</p>
<fieldset class="mode-control"><legend>Appearance</legend><div class="segmented" id="modes">
<label><input type="radio" name="mode" value="light" checked><span>Light</span></label>
<label><input type="radio" name="mode" value="dim"><span>Dim</span></label>
<label><input type="radio" name="mode" value="dark"><span>Dark</span></label>
</div></fieldset>
<label class="field" for="palette">Color palette<select id="palette"></select></label>
<label class="field" for="font">Typography<select id="font"></select></label>
<label class="field" for="mark">Logo concept<select id="mark"></select></label>
<p class="local-note">Preview only. Your choices stay in this browser when storage is available.</p>
<nav aria-label="Brand board sections">
<a href="#identity"><span>01</span> Identity</a>
<a href="#typography"><span>02</span> Typography</a>
<a href="#color"><span>03</span> Color system</a>
<a href="#components"><span>04</span> Iconography & controls</a>
<a href="#review"><span>05</span> Your review</a>
</nav>
<button id="reset" class="text-button" type="button">Reset preview</button>
</div>
</aside>
<main id="main" tabindex="-1">
<noscript><p class="notice">JavaScript is needed for these interactive studies. Enable it and reload. The requirements and review notes are also available as Markdown files in this folder.</p></noscript>
<section class="intro" aria-labelledby="intro-title">
<div class="intro-copy"><p class="eyebrow">Mosaic Stack / identity exploration</p>
<h1 id="intro-title">One identity.<br>Many ways to work.</h1>
<p class="lead">An AI operating system for the things you make, manage, and do together.</p>
<p>Let's choose the visual language before we choose the dashboard. Compare three marks, three sans-serif families, and ten palettes in three appearances.</p>
<a href="#identity" class="inline-link">Start with the mark <span aria-hidden="true"></span></a>
</div>
<div class="identity-stage" aria-label="Current brand combination">
<div class="stage-meta"><span id="current-palette">Harbor</span><span id="current-mode">Light</span></div>
<div class="stage-mark" data-logo></div>
<div class="stage-wordmark">Mosaic Stack<span>mosaicstack.dev</span></div>
<div class="stage-bottom"><span>Independent pieces.<br>A shared place to work.</span><span class="stage-swatch" aria-hidden="true"></span></div>
</div>
</section>
<section id="identity" class="board-section" aria-labelledby="identity-title">
<div class="section-heading"><div><p class="eyebrow">01 / Identity</p><h2 id="identity-title">Recognizable without a color.</h2></div><p>Each concept starts as a single-color shape. Choose one to see it in the page header and brand specimen.</p></div>
<div id="logo-grid" class="three-grid"></div>
<p class="section-note">Original concept studies, not cleared trademarks. Small-size recognition and final proportions need your judgment. No logo is approved yet.</p>
</section>
<section id="typography" class="board-section" aria-labelledby="type-title">
<div class="section-heading"><div><p class="eyebrow">02 / Typography</p><h2 id="type-title">A voice you can read all day.</h2></div><p>Compare the same content at the same sizes. Each choice changes the board, while these specimens keep their own typeface.</p></div>
<div id="font-grid" class="three-grid"></div>
<div class="type-scale"><span><b>32</b>Section heading</span><span><b>20</b>Card title</span><span><b>16</b>Body & controls</span><span><b>13</b>Supporting labels</span><p>Sentence case. Tabular numerals for data. Comfortable line spacing. Monospace reserved for actual code in later designs.</p></div>
<p class="section-note">Local Latin font files, four weights each, licensed under SIL OFL. Other scripts fall back to system fonts and need later multilingual testing.</p>
</section>
<section id="color" class="board-section" aria-labelledby="color-title">
<div class="section-heading"><div><p class="eyebrow">03 / Color system</p><h2 id="color-title">Ten palettes. Same Mosaic.</h2></div><p>Hue relationships give each palette a reason. Contrast determines the usable shades. Choose any appearance directly on a palette card.</p></div>
<div class="color-principles"><p><b>Light</b>Pale tinted canvas, clean surfaces.</p><p><b>Dim</b>Charcoal layers with a restrained tint.</p><p><b>Dark</b>Deep color, with lighter raised surfaces.</p></div>
<div id="palette-grid" class="palette-grid"></div>
<div class="token-panel"><div><h3 id="token-title">Current tokens</h3><p>Actual values used by this preview, not production configuration.</p><button type="button" id="export" class="secondary">Download palette tokens</button></div><dl id="tokens"></dl></div>
<p class="section-note">Success, warning, and error are separate roles. They always have a label or symbol. A red brand palette never makes color alone mean "error".</p>
</section>
<section id="components" class="board-section" aria-labelledby="components-title">
<div class="section-heading"><div><p class="eyebrow">04 / Iconography & controls</p><h2 id="components-title">Quiet details. Clear meaning.</h2></div><p>One original outline family, with a 24-unit grid and consistent 1.75-unit strokes. Labels carry meaning; icons help recognition.</p></div>
<div id="icon-grid" class="icon-grid"></div>
<div class="component-grid">
<div class="component-panel"><p class="eyebrow">Interaction specimen / local only</p><h3>A useful bit of feedback</h3><p>Try the button and state selector. No workspace or agent is created.</p>
<label class="field" for="sample-title">Example project name<input id="sample-title" type="text" value="Summer reading notes" maxlength="160" aria-describedby="sample-help"></label>
<p id="sample-help" class="small">This field stays intact when you preview an error.</p>
<label class="field" for="sample-state">Component state<select id="sample-state"><option value="ready">Ready</option><option value="loading">Loading</option><option value="empty">Empty</option><option value="error">Error</option><option value="success">Success</option></select></label>
<div id="sample-feedback" class="feedback" role="status"></div>
<div class="button-row"><button id="sample-action" class="primary" type="button">Preview success</button><button type="button" class="secondary" disabled>Unavailable</button></div>
</div>
<div class="component-panel"><p class="eyebrow">Surface & status specimen</p><h3>Depth without a gradient</h3>
<div class="layer-sample"><span>Canvas</span><div><span>Surface</span><div>Raised surface <span class="sample-badge">Selected</span></div></div></div>
<ul class="status-list"><li class="success"><span data-icon="check"></span>Ready for review</li><li class="warning"><span data-icon="warning"></span>Needs your attention</li><li class="danger"><span data-icon="error"></span>Could not save. Try again.</li></ul>
<p class="small">8 px control corners, 16 px comparison panels, and a 4 px spacing scale. No animation is required to understand a state change.</p>
</div>
</div>
</section>
<section id="review" class="board-section review-section" aria-labelledby="review-title">
<div><p class="eyebrow">05 / Your review</p><h2 id="review-title">Choose a direction,<br>not a finished brand.</h2><p class="lead">My starting recommendation is Assembly, DM Sans, and Harbor.</p><p>The mark connects to the name, the font stays approachable, and blue gets room to be blue. Relay and Aperture offer less literal alternatives.</p></div>
<div class="review-panel"><h3>What I'd like your take on</h3><ol><li>Which mark feels like Mosaic, including at 16 px?</li><li>Which font feels best in controls and longer text?</li><li>Which palette should be the default? Try it in all three appearances.</li><li>What should feel different before we design the dashboards?</li></ol>
<label class="field" for="review-notes">Your notes<textarea id="review-notes" rows="4" placeholder="Try Relay with DM Sans. Harbor is close, but…"></textarea></label>
<p class="small">Notes stay in this browser if storage is available. Download a copy to keep them. Nothing is sent to Dewey.</p>
<button type="button" class="primary" id="download-review">Download review notes</button>
<p id="selection-summary" class="small"></p>
</div>
</section>
<footer><p>Local brand prototype · Not a live Mosaic Stack interface</p><p>Branding review comes next. The five dashboard designs have not been built.</p><a href="RESEARCH.md">Reference observations & inspection limits</a></footer>
</main>
</div>
<p id="announcement" class="sr-only" role="status" aria-live="polite"></p>
</body>
</html>
+169
View File
@@ -0,0 +1,169 @@
@font-face{font-family:'DM Sans';src:url('assets/fonts/dm-sans-400.woff2') format('woff2');font-weight:400;font-display:swap}
@font-face{font-family:'DM Sans';src:url('assets/fonts/dm-sans-500.woff2') format('woff2');font-weight:500;font-display:swap}
@font-face{font-family:'DM Sans';src:url('assets/fonts/dm-sans-600.woff2') format('woff2');font-weight:600;font-display:swap}
@font-face{font-family:'DM Sans';src:url('assets/fonts/dm-sans-700.woff2') format('woff2');font-weight:700;font-display:swap}
@font-face{font-family:'IBM Plex Sans';src:url('assets/fonts/ibm-plex-sans-400.woff2') format('woff2');font-weight:400;font-display:swap}
@font-face{font-family:'IBM Plex Sans';src:url('assets/fonts/ibm-plex-sans-500.woff2') format('woff2');font-weight:500;font-display:swap}
@font-face{font-family:'IBM Plex Sans';src:url('assets/fonts/ibm-plex-sans-600.woff2') format('woff2');font-weight:600;font-display:swap}
@font-face{font-family:'IBM Plex Sans';src:url('assets/fonts/ibm-plex-sans-700.woff2') format('woff2');font-weight:700;font-display:swap}
@font-face{font-family:Manrope;src:url('assets/fonts/manrope-400.woff2') format('woff2');font-weight:400;font-display:swap}
@font-face{font-family:Manrope;src:url('assets/fonts/manrope-500.woff2') format('woff2');font-weight:500;font-display:swap}
@font-face{font-family:Manrope;src:url('assets/fonts/manrope-600.woff2') format('woff2');font-weight:600;font-display:swap}
@font-face{font-family:Manrope;src:url('assets/fonts/manrope-700.woff2') format('woff2');font-weight:700;font-display:swap}
:root{--canvas:#f3f5f7;--surface:#fff;--raised:#e8ebef;--text:#283343;--muted:#505c6b;--action:#215fac;--onAction:#fff;--accent:#98642e;--line:#cbd1d9;--border:#6e7b8d;--focus:#215fac;--font:'DM Sans',system-ui,sans-serif;color-scheme:light}
*{box-sizing:border-box}
html{scroll-padding-top:24px}
body{margin:0;background:var(--canvas);color:var(--text);font:400 1rem/1.55 var(--font);overflow-wrap:break-word}
button,input,select,textarea{font:inherit}
button,select{cursor:pointer}
button,a,input,select,textarea{-webkit-tap-highlight-color:transparent}
a{color:var(--action);text-underline-offset:4px}
a:hover{text-decoration-thickness:2px}
:focus-visible{outline:3px solid var(--focus);outline-offset:4px}
button:disabled{cursor:not-allowed;opacity:.55}
button{border:1px solid var(--border);border-radius:8px;padding:10px 16px;background:var(--surface);color:var(--text);min-height:44px;font-weight:600;line-height:1.4}
button:hover:not(:disabled){background:var(--raised)}
button.primary{background:var(--action);color:var(--onAction);border-color:var(--action)}
button.primary:hover{box-shadow:inset 0 0 0 2px var(--onAction)}
input,select,textarea{width:100%;min-width:0;min-height:44px;border:1px solid var(--border);border-radius:8px;padding:9px 12px;background:var(--surface);color:var(--text)}
textarea{resize:vertical}
textarea::placeholder{color:var(--muted);opacity:1}
p{margin:0 0 16px;max-width:68ch}
h1,h2,h3{line-height:1.15;letter-spacing:-.035em;margin:0 0 16px;font-weight:600;overflow-wrap:anywhere}
h1{font-size:clamp(2.4rem,3.9vw,5.75rem);letter-spacing:-.055em}
h2{font-size:2rem}
h3{font-size:1.25rem;letter-spacing:-.025em}
.logo{display:block;flex-shrink:0}
.icon{width:24px;height:24px;display:inline-block;flex-shrink:0;vertical-align:middle}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}
.skip{position:fixed;left:16px;top:-100px;background:var(--surface);padding:12px 16px;z-index:10}
.skip:focus{top:12px}
.masthead{display:flex;align-items:center;justify-content:space-between;gap:24px;padding:22px 32px;border-bottom:1px solid var(--line);background:var(--surface)}
.brand-home{display:flex;align-items:center;gap:12px;color:var(--text);font-size:20px;font-weight:600;letter-spacing:-.035em;text-decoration:none;min-height:44px}
.brand-home .logo{width:32px;height:32px;color:var(--action)}
.masthead-note{display:flex;align-items:center;gap:16px;font-size:14px;color:var(--muted)}
.edition{border-left:1px solid var(--line);padding-left:16px}
.review-link{font-size:14px;min-height:44px;display:flex;align-items:center;gap:24px}
.layout{display:grid;grid-template-columns:248px minmax(0,1fr)}
.controls{border-right:1px solid var(--line);padding:32px 24px}
.control-inner{position:sticky;top:24px;max-height:calc(100dvh - 48px);overflow-y:auto;padding:6px;margin:-6px}
.eyebrow{text-transform:uppercase;letter-spacing:.11em;font-size:12px;font-weight:600;color:var(--muted);margin-bottom:12px}
.control-intro{font-size:18px;line-height:1.4;letter-spacing:-.02em;margin-bottom:28px}
.field{display:block;font-size:14px;font-weight:500;margin-bottom:18px}
.field select,.field input,.field textarea{display:block;margin-top:7px;font-size:16px;font-weight:400}
.mode-control{border:0;margin:0 0 20px;padding:0;min-width:0}
.mode-control legend{font-size:14px;font-weight:500;margin-bottom:7px;padding:0}
.segmented{display:flex;gap:4px;background:var(--raised);padding:4px;border-radius:10px}
.segmented label{flex:1;position:relative;min-width:0;cursor:pointer}
.segmented input{position:absolute;opacity:0;width:100%;height:100%;margin:0;min-height:44px;cursor:pointer}
.segmented span{display:block;text-align:center;padding:12px 3px;border-radius:7px;font-size:13px;line-height:20px}
.segmented input:checked+span{background:var(--action);color:var(--onAction);font-weight:600}
.segmented input:focus-visible+span{outline:3px solid var(--focus);outline-offset:4px}
.local-note,.small,.section-note{font-size:13px;color:var(--muted);line-height:1.6}
.controls nav{display:grid;gap:4px;border-top:1px solid var(--line);padding:20px 0;margin-top:24px}
.controls nav a{display:flex;gap:14px;align-items:center;padding:10px 0;text-decoration:none;color:var(--text);font-size:14px;min-height:44px}
.controls nav a:hover{color:var(--action);text-decoration:underline}
.controls nav span{color:var(--muted);font-size:12px;font-variant-numeric:tabular-nums}
.text-button{border:0;padding:8px 0;color:var(--action);background:none;font-size:14px;text-decoration:underline;text-underline-offset:4px}
main{min-width:0;padding:48px clamp(24px,3vw,80px) 0}
.intro{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,.85fr);gap:clamp(24px,4vw,100px);align-items:center;padding:12px 0 64px}
.intro-copy>p:not(.eyebrow){color:var(--muted)}
.lead{font-size:20px;line-height:1.45;letter-spacing:-.02em}
.inline-link{display:inline-flex;align-items:center;gap:36px;min-height:44px;font-weight:600;margin-top:8px}
.identity-stage{display:flex;flex-direction:column;align-items:center;min-height:450px;border-radius:4px 64px 4px 4px;background:var(--raised);padding:28px;color:var(--text)}
.stage-meta{width:100%;display:flex;justify-content:space-between;gap:12px;font-size:12px;color:var(--muted)}
.stage-mark{margin:40px 0 20px;color:var(--action)}
.stage-mark .logo{width:140px;height:140px}
.stage-wordmark{font-size:clamp(1.75rem,2vw,3rem);font-weight:600;letter-spacing:-.045em;text-align:center;line-height:1.1}
.stage-wordmark>span{display:block;font-size:13px;letter-spacing:0;font-weight:400;color:var(--muted);margin-top:12px}
.stage-bottom{display:flex;justify-content:space-between;align-items:flex-end;gap:24px;width:100%;margin-top:36px;font-size:12px;line-height:1.5;color:var(--muted)}
.stage-swatch{width:32px;height:32px;background:var(--accent);border-radius:0 12px 0 0;flex-shrink:0}
.board-section{padding:48px 0 52px;border-top:1px solid var(--line);scroll-margin-top:24px}
.section-heading{display:flex;align-items:flex-end;justify-content:space-between;gap:32px;margin-bottom:28px}
.section-heading>div{flex:1;min-width:0}
.section-heading>p{max-width:43ch;color:var(--muted);font-size:14px;flex:.8}
.section-heading h2{margin-bottom:0;max-width:24ch}
.three-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:20px}
.study-card{background:var(--surface);border:1px solid var(--line);border-radius:16px;padding:24px;display:flex;flex-direction:column;min-width:0}
.study-card.is-selected{border-color:var(--action);box-shadow:inset 0 0 0 1px var(--action)}
.card-kicker{font-size:12px;color:var(--muted);margin-bottom:16px;display:flex;justify-content:space-between;gap:8px;flex-wrap:wrap}
.selection-label{font-weight:600;color:var(--action)}
.logo-display{color:var(--action);display:flex;align-items:center;justify-content:center;min-height:168px;background:var(--canvas);border-radius:10px;margin-bottom:24px}
.logo-display .logo{width:110px;height:110px}
.study-card p{font-size:14px;color:var(--muted)}
.study-card .tradeoff{font-size:13px}
.study-card .choose{margin-top:auto;align-self:flex-start;width:100%}
.size-strip{display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;gap:16px 12px;margin:0 0 20px;padding-bottom:20px;border-bottom:1px solid var(--line)}
.size-strip>span{display:grid;justify-items:center;gap:8px;font-size:11px;color:var(--muted)}
.size-strip .logo{color:var(--text)}
.size-strip .reverse{background:var(--text);color:var(--surface);padding:6px;border-radius:4px}
.section-note{margin-top:20px;margin-bottom:0;max-width:85ch}
.font-title{font-size:28px;margin-bottom:20px;letter-spacing:-.04em}
.type-specimen{border-top:1px solid var(--line);border-bottom:1px solid var(--line);padding:20px 0;margin-bottom:20px}
.type-specimen .type-heading{font-size:24px;font-weight:600;line-height:1.25;color:var(--text);margin-bottom:12px}
.type-specimen p{font-size:16px;color:var(--text)}
.type-specimen .numerals{font-variant-numeric:tabular-nums;font-size:18px;letter-spacing:.03em;margin-bottom:0}
.type-scale{display:flex;flex-wrap:wrap;gap:24px;padding:28px 0 0;align-items:center}
.type-scale>span{font-size:12px;color:var(--muted);display:grid;gap:8px;min-width:100px}
.type-scale b{font-size:28px;line-height:1;color:var(--text);font-weight:500}
.type-scale p{font-size:13px;color:var(--muted);max-width:38ch;margin:0 0 0 auto}
.color-principles{display:flex;gap:32px;flex-wrap:wrap;margin-bottom:28px}
.color-principles p{font-size:14px;color:var(--muted);margin-bottom:0}
.color-principles b{display:block;color:var(--text);font-weight:600;margin-bottom:4px}
.palette-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:20px}
.palette-card{border:1px solid var(--line);background:var(--surface);border-radius:16px;padding:24px;display:flex;flex-direction:column;min-width:0}
.palette-card.is-selected{border-color:var(--action);box-shadow:inset 0 0 0 1px var(--action)}
.palette-card h3{display:flex;justify-content:space-between;gap:8px}
.palette-card h3 span{font-size:12px;line-height:1.7;letter-spacing:0;color:var(--action)}
.palette-swatches{display:flex;height:68px;gap:4px;margin-bottom:20px;border-radius:8px;overflow:hidden}
.palette-swatches i:first-child{flex:2}
.palette-swatches i{flex:1}
.palette-card .theory{font-size:12px;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);margin-bottom:8px}
.palette-card p{font-size:14px;color:var(--muted)}
.palette-card .palette-use{font-size:13px;margin-top:auto}
.palette-modes{display:flex;gap:8px;margin-top:4px;flex-wrap:wrap}
.palette-modes button{flex:1;min-width:64px;padding:10px 4px;font-size:13px;background:var(--mini-surface);color:var(--mini-text);border-color:var(--mini-border)}
.palette-modes button[aria-pressed=true]{box-shadow:inset 0 -3px 0 currentColor;font-weight:700}
.palette-modes button:hover{background:var(--mini-raised)}
.token-panel{margin-top:28px;border:1px solid var(--line);border-radius:16px;padding:24px;display:grid;grid-template-columns:minmax(0,.8fr) minmax(0,1.5fr);gap:32px}
.token-panel p{font-size:14px;color:var(--muted)}
.token-panel dl{margin:0;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:20px}
.token-panel dt{font-size:12px;color:var(--muted);display:flex;gap:8px;align-items:center}
.token-panel dt i{width:12px;height:12px;border:1px solid var(--border);border-radius:2px;flex-shrink:0}
.token-panel dd{font-size:13px;font-variant-numeric:tabular-nums;margin:4px 0 0 20px}
.icon-grid{display:grid;grid-template-columns:repeat(8,minmax(0,1fr));border:1px solid var(--line);border-radius:12px;overflow:hidden;margin-bottom:24px}
.icon-specimen{display:flex;flex-direction:column;align-items:center;gap:16px;padding:28px 8px;background:var(--surface);text-align:center;font-size:12px}
.icon-specimen .icon{color:var(--text)}
.icon-specimen>span{max-width:100%;overflow-wrap:anywhere}
.component-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:24px}
.component-panel{background:var(--surface);border:1px solid var(--line);border-radius:16px;padding:28px;min-width:0}
.component-panel>p{font-size:14px;color:var(--muted)}
.button-row{display:flex;gap:12px;flex-wrap:wrap;margin-top:20px}
.feedback{padding:16px;border:1px solid var(--border);border-radius:8px;min-height:64px;background:var(--raised);display:flex;gap:10px;align-items:flex-start;font-size:14px}
.feedback[data-state=error]{color:var(--danger);border-color:var(--danger)}
.feedback[data-state=success]{color:var(--success);border-color:var(--success)}
.layer-sample{background:var(--canvas);padding:20px;border:1px solid var(--line);border-radius:8px;font-size:13px}
.layer-sample>div{padding:20px;margin-top:12px;background:var(--surface);border:1px solid var(--line);border-radius:8px}
.layer-sample>div>div{padding:20px;margin-top:12px;background:var(--raised);border-radius:8px;display:flex;justify-content:space-between;gap:12px;flex-wrap:wrap}
.sample-badge{color:var(--action);font-weight:600}
.status-list{list-style:none;margin:24px 0;padding:0;display:grid;gap:12px;font-size:14px}
.status-list li{display:flex;gap:10px;align-items:center}
.success{color:var(--success)}.warning{color:var(--warning)}.danger{color:var(--danger)}
.review-section{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:48px;align-items:start}
.review-section>div{min-width:0}
.review-section>div>p:not(.eyebrow):not(.lead){color:var(--muted)}
.review-panel{background:var(--raised);border-radius:16px;padding:28px}
.review-panel ol{padding-left:20px;font-size:14px;display:grid;gap:10px;margin:0 0 24px}
.review-panel li{padding-left:5px}
#selection-summary{margin:16px 0 0}
footer{border-top:1px solid var(--line);padding:24px 0 36px;color:var(--muted);font-size:13px;display:flex;gap:12px 28px;flex-wrap:wrap}
footer p{margin:0}
footer a{color:var(--muted)}
.notice{padding:20px;border:2px solid var(--border);background:var(--surface)}
@media(min-width:1700px){.palette-grid{grid-template-columns:repeat(5,minmax(0,1fr))}.intro{grid-template-columns:minmax(0,1.2fr) minmax(0,1fr)}.identity-stage{min-height:520px}.stage-mark .logo{width:180px;height:180px}.study-card{padding:32px}.logo-display{min-height:220px}.logo-display .logo{width:140px;height:140px}}
@media(min-width:2400px){.layout{grid-template-columns:280px minmax(0,1fr)}.controls{padding:40px 32px}.intro-copy{max-width:900px}.intro{padding-bottom:88px}.identity-stage{min-height:570px}.stage-mark .logo{width:220px;height:220px}.study-card p{max-width:65ch}.section-heading>p{max-width:60ch;flex:1}.palette-card{padding:28px}.logo-display{min-height:280px}.token-panel dl{grid-template-columns:repeat(5,minmax(0,1fr))}}
@media(max-width:1199px){.layout{grid-template-columns:220px minmax(0,1fr)}.controls{padding:28px 16px}main{padding:32px 24px 0}.intro{gap:24px}.identity-stage{padding:20px;min-height:420px}.three-grid{gap:12px}.study-card{padding:16px}.section-heading{display:block}.section-heading>p{max-width:70ch;margin:16px 0 0}.font-title{font-size:24px}.icon-grid{grid-template-columns:repeat(4,minmax(0,1fr))}.token-panel{grid-template-columns:1fr}.component-panel{padding:20px}.review-section{gap:24px}}
@media(max-width:959px){.masthead{padding:16px 24px}.masthead-note{display:none}.layout{grid-template-columns:1fr}.controls{border-right:0;border-bottom:1px solid var(--line);padding:20px 24px}.control-inner{position:static;max-height:none;overflow:visible;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:16px}.control-inner>.eyebrow,.control-intro,.local-note,.controls nav,.control-inner>.text-button{grid-column:1/-1}.control-inner>.eyebrow{margin:0}.control-intro{display:none}.mode-control,.field{margin-bottom:0}.local-note{margin:0}.controls nav{display:flex;flex-wrap:wrap;gap:8px 20px;padding:8px 0 0;margin:0}.controls nav a{font-size:13px}.controls nav span{display:none}.control-inner>.text-button{justify-self:start;padding:0;min-height:30px}.intro{padding:16px 0 40px}.three-grid{gap:16px}.component-panel .field{margin-bottom:18px}.review-panel .field{margin-bottom:18px}h1{font-size:clamp(2.5rem,5.5vw,4rem)}}
@media(max-width:699px){.masthead{padding:12px 20px;gap:12px}.brand-home{font-size:18px;gap:8px}.review-link{gap:8px;font-size:13px}.brand-home .logo{width:28px;height:28px}.controls{padding:20px}.control-inner{grid-template-columns:repeat(auto-fit,minmax(min(100%,9em),1fr));gap:16px}.mode-control{grid-column:1/-1}.control-inner>.field:last-of-type{grid-column:1/-1}main{padding:28px 20px 0}.intro{grid-template-columns:1fr;gap:24px}.intro h1{font-size:clamp(2.5rem,9vw,4rem)}.intro-copy>p{max-width:48ch}.identity-stage{min-height:380px}.stage-mark{margin:24px 0 16px}.stage-wordmark{font-size:32px}.three-grid,.palette-grid,.component-grid,.review-section{grid-template-columns:1fr}.study-card{padding:24px}.logo-display{min-height:160px}.size-strip{justify-content:flex-start;gap:32px}.board-section{padding:32px 0}h2{font-size:28px}.type-scale{gap:24px}.type-scale p{margin:0}.token-panel dl{grid-template-columns:repeat(2,minmax(0,1fr))}.token-panel{padding:20px}.icon-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.icon-specimen{padding:20px 8px;font-size:12px}.review-panel{padding:20px}.color-principles{gap:16px}.color-principles p{width:100%}.color-principles b{display:inline-block;min-width:52px;margin:0}.layer-sample,.layer-sample>div,.layer-sample>div>div{padding:12px}.review-section{gap:20px}}
@media(prefers-reduced-motion:reduce){*,*::before,*::after{scroll-behavior:auto!important;animation:none!important;transition:none!important}}
@media(forced-colors:active){.study-card.is-selected,.palette-card.is-selected{outline:2px solid Highlight}.segmented input:checked+span{outline:2px solid Highlight}.palette-swatches{border:1px solid CanvasText}}
+38
View File
@@ -0,0 +1,38 @@
===== FILBERT NATIVE DEVELOPMENT CONTEXT =====
Your identity is Filbert. This launch runs Pi directly on the host, in the
Mosaic Stack development repository. The injected SOUL defines your persona;
CONSTITUTION and STANDARDS supply governance, USER supplies user context,
and AGENTS.md supplies repository instructions.
You have host read, bash, edit, write, grep, find, and ls tools. This is a
development TUI with the operator's OS access, not a sandbox or a registered
managed fleet seat. Use repository scripts for Mosaic operations and inspect
their effects before running them. Container paths in skills describe worker
deployments, not your current workspace. A tool's presence is not authority
to change unrelated files, other agents' work, or the live fleet.
For an assigned improvement, inspect the implementation, reproduce the issue,
make the smallest useful change, verify it, and continue through the authorized
outcome. Read docs/plans/CURRENT.md to reconcile ownership and existing gates;
a new user assignment does not silently resume unrelated queued work.
The local /goal extension is loaded and owns any operator-set goal lifecycle.
Use ms-proactive-agent for work selection and ms-goal for recovery guidance;
do not create a competing goal loop. Follow goal_report's actual schema and
reporting instructions. Its text format is Just Completed / Next Step /
Blocked, with '* none' for empty sections. No external reporting skill is
needed to discover that format. Native development packaging supersedes
older skill statements that this extension is unavailable.
The canonical checkout is /mnt/storage/src/mosaic-stack; v1/ is archived
legacy source. Work on the current foundation unless the user explicitly
assigns legacy work. Your general development responsibilities are defined in SOUL.
Darkwing is the Mosaic Stack development team lead.
Conversation history persists across launcher restarts. Goals belong to a
single process incarnation; recover the assignment from verified records and
the operator's direction after a restart. No goal is started by this launcher.
Context is captured anew at launch; source edits do not update this process's
injected snapshot. Relaunch to load approved context changes.
+65
View File
@@ -0,0 +1,65 @@
# Filbert development TUI
From any terminal, run:
```sh
/mnt/storage/src/mosaic-stack/agents/filbert/launch.sh
```
The agent launcher is a thin shim to `scripts/agent.sh --host-dev filbert`,
forwarding context/session arguments and fixing the model to
`openai-codex/gpt-6-astra` with `low` thinking. `scripts/agent.sh` is the common entry
point; `scripts/agent-host-dev.sh` implements its native development mode.
The host launcher opens the repository as Filbert's workspace.
It uses the repository-pinned Pi, OpenAI Codex GPT-6 Astra with low thinking, and
native Pi authentication (normal `~/.pi/agent`, or `PI_CODING_AGENT_DIR` if
explicitly set). It never copies credentials. Install dependencies with
`npm ci --ignore-scripts --no-audit --no-fund` if needed.
`--check` validates configuration and required inputs without opening Pi or
calling a model. `--fresh` starts a new conversation without deleting earlier
ones. Normal launches continue the latest conversation under
`.pi/state/filbert/sessions/`; the first launch creates one. A launcher lock
rejects simultaneous launches through this script. It does not exclude Pi
processes started another way. Damaged JSONL history refuses automatic resume;
`--fresh` is an explicit escape hatch that preserves the damaged evidence.
The current files are combined into a private launch snapshot under
`.pi/state/filbert/launches/`:
- `contracts/CONSTITUTION.md` and `contracts/STANDARDS.md`
- `agents/filbert/SOUL.md`
- `<configured dataRoot>/user/USER.md`, the deployment's live user profile
- the repository's `AGENTS.md` and Filbert's `CONTEXT.md`
Use `--soul FILE`, `--constitution FILE`, or `--user FILE` to select alternate
inputs, including a future `contracts/USER.md`. Relative paths resolve from
the repository root. Missing or empty inputs refuse launch. Snapshots can
contain personal context and remain local, with private file permissions.
Context edits take effect on relaunch, including when resuming a conversation.
The launcher enables coding/search tools, `goal_report`, ten explicit local
skills, and the canonical goal extension through `scripts/sync-dev-extensions.sh`.
Ambient context, skills, extensions, templates, and themes are disabled.
The normal Pi coding prompt is retained with the Mosaic context appended.
Enter `/goal <assignment and acceptance criteria>` to start continuing work;
`/goal stop`, `/goal resume`, and `/goal` pause, resume, and inspect it. A new
process does not automatically adopt a previous process's goal.
This TUI has the operator's host access, including repository edits and host
commands. Its tool list is not OS isolation. It creates no managed role or
fleet registration. Worker dispatch still uses the governed Mosaic task runner.
The user supplies the assignment; launch alone does not start self-modification.
## Deployment findings
The existing `scripts/agent.sh` launches a Docker container, defaults to the
`agent-<name>` session directory, and asks Pi to continue when that directory
is nonempty. Its default workspace is `<dataRoot>/workspaces/<name>`, not this
checkout. `src/load-contracts.sh` loads image-baked governance, an optional
seat SOUL override, live user Markdown, and mission context into a shared
prompt path. A seat override requires `agent.json`; a standalone SOUL is not
discovered. `adapters/pi/adapter.sh` disables extensions. The temporary host
launcher follows the existing native development path to provide repository
access and `/goal`, and keeps its conversations separate from container and
live fleet sessions. It does not invoke release alignment on startup.
+21
View File
@@ -0,0 +1,21 @@
# SOUL — Filbert
You are Filbert, a general development collaborator on Mosaic Stack.
Darkwing is the team lead for Mosaic Stack development. Work on the concrete
assignments Jason or Darkwing gives you: implementation, investigation,
testing, debugging, documentation, or review as the project needs.
Investigate before guessing. Carry authorized work through implementation
and appropriate verification. State what changed, the evidence that it
works, and any remaining limitations. Distinguish observed behavior from
assumptions and report blockers with the next decision needed.
Coordinate scope and ownership with Darkwing. Preserve other agents' edits
and append-only records, and avoid overlapping changes without reconciling
ownership. Dewey owns frontend design and UX; involve that role when a task
needs interface design direction. Review independently when assigned and
base conclusions on evidence rather than the author's confidence.
Follow repository governance and the user's current direction. Team roles
do not grant new policy, deployment, credential, or push authority. Launch
alone does not assign a task or resume unrelated queued work.
+6
View File
@@ -0,0 +1,6 @@
#!/usr/bin/env bash
# Filbert's native development mode through the Mosaic agent entry point.
set -euo pipefail
REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
exec "$REPO/scripts/agent.sh" --host-dev filbert "$@" \
--provider openai-codex --model gpt-6-astra --thinking low
+21
View File
@@ -0,0 +1,21 @@
// Refuse damaged history before Pi's --continue can silently skip it.
import { readFileSync, lstatSync } from 'node:fs';
try {
for (const file of process.argv.slice(2)) {
if (!lstatSync(file).isFile()) throw new Error(`not a regular session file: ${file}`);
const lines = readFileSync(file, 'utf8').trim().split('\n');
const entries = lines.map((line) => JSON.parse(line));
const header = entries[0];
if (header?.type !== 'session' || typeof header.id !== 'string' || !header.id ||
typeof header.version !== 'number' || typeof header.cwd !== 'string' ||
!Number.isFinite(Date.parse(header.timestamp)) ||
entries.slice(1).some((entry) => !entry || typeof entry.type !== 'string')) {
throw new Error(`invalid session structure: ${file}`);
}
if (header.cwd !== process.cwd()) throw new Error(`session belongs to another workspace: ${file}`);
}
} catch (error) {
console.error(`filbert: cannot safely resume: ${error.message}; inspect history or explicitly use --fresh`);
process.exit(1);
}
+5
View File
@@ -0,0 +1,5 @@
# SOUL - researcher
You are the researcher seat of the Mosaic fleet. You are curious, methodical,
and precise. You cite what you know, admit what you do not, and never guess
when you can verify.
+6
View File
@@ -0,0 +1,6 @@
{
"agentVersion": 1,
"name": "researcher",
"role": "researcher",
"capabilities": { "tools": ["read", "bash"] }
}
+23
View File
@@ -0,0 +1,23 @@
===== ROCKO NATIVE DEVELOPMENT CONTEXT =====
Your identity is Rocko. This is Claude Code running on the host in the Mosaic
Stack repository, using the Sonnet model. Darkwing is the development team
lead; your SOUL defines your general project responsibilities. CONSTITUTION
and STANDARDS supply governance, USER supplies user context, and AGENTS.md
supplies repository instructions.
Use the actual Claude Code tools and capabilities available in this session.
This launcher does not load Pi extensions or Pi's goal_report tool. Do not
claim that Pi's /goal lifecycle is available here. Claude Code retains its
normal authentication, settings, discovered context, and permission behavior.
Use project skills from skills/ when relevant and follow their actual inputs.
Read docs/plans/CURRENT.md to reconcile current ownership and existing gates.
A new user assignment does not silently resume unrelated queued work. The
canonical checkout is /mnt/storage/src/mosaic-stack; v1/ is archived legacy
source. Preserve other agents' work and coordinate scope with Darkwing.
The launcher records Rocko's own Claude session ID and resumes that ID on
subsequent launches. Context is captured anew on launch; relaunch to load
approved context edits. Launching alone does not assign work. This process
has host access and is not a sandbox or a registered managed fleet seat.
+39
View File
@@ -0,0 +1,39 @@
# Rocko development TUI
Run from any terminal:
```sh
/mnt/storage/src/mosaic-stack/agents/rocko/launch.sh
```
Rocko handles general Mosaic Stack development assignments under team lead
Darkwing. The launcher opens Claude Code in the repository with `--model sonnet`
and the display name Rocko. Sonnet is the selected CLI model alias; Rocko's
project persona is supplied by SOUL.md, not a separate custom Claude agent.
Use `--check` to validate the executable and context inputs without a model
call. This does not verify authentication or account access to Sonnet. Claude
Code uses its normal authentication, settings, permissions, and discovered
resources; this script does not copy credentials or bypass permissions.
Normal launches resume the exact Claude UUID recorded locally in
`.pi/state/rocko/session-id`. First launch creates a UUID; `--fresh` creates
another while retaining previous conversations in Claude's native storage.
Each private launch receipt under `.pi/state/rocko/launches/` retains its UUID
and context snapshot. The launcher lock refuses concurrent Rocko launches
through this script; it does not lock sessions opened by other means.
If Claude exits before saving its first conversation, or its history is
removed, the saved UUID may not be resumable. Inspect the failure and use
`--fresh` explicitly to start again. The launcher does not fall back to the
latest unrelated project conversation. Old UUIDs in launch receipts can be
opened manually with `claude --resume UUID` from the project directory.
The prompt snapshot includes CONSTITUTION, STANDARDS, Rocko's SOUL, the live
Mosaic user profile, root AGENTS.md, and Rocko's CONTEXT.md. `--soul FILE`,
`--constitution FILE`, and `--user FILE` override individual inputs; relative
paths resolve from the repository root. Missing or empty inputs refuse launch.
The snapshot is appended to Claude's system prompt on each launch.
This is a host development session, not a managed fleet registration. It
loads no Pi goal extension. The user or team lead supplies the assignment.
+21
View File
@@ -0,0 +1,21 @@
# SOUL — Rocko
You are Rocko, a general development collaborator on Mosaic Stack.
Darkwing is the team lead for Mosaic Stack development. Work on the concrete
assignments Jason or Darkwing gives you: implementation, investigation,
testing, debugging, documentation, or review as the project needs.
Investigate before guessing. Carry authorized work through implementation
and appropriate verification. State what changed, the evidence that it
works, and any remaining limitations. Distinguish observed behavior from
assumptions and report blockers with the next decision needed.
Coordinate scope and ownership with Darkwing. Preserve other agents' edits
and append-only records, and avoid overlapping changes without reconciling
ownership. Dewey owns frontend design and UX; involve that role when a task
needs interface design direction. Review independently when assigned and
base conclusions on evidence rather than the author's confidence.
Follow repository governance and the user's current direction. Team roles
do not grant new policy, deployment, credential, or push authority. Launch
alone does not assign a task or resume unrelated queued work.
+82
View File
@@ -0,0 +1,82 @@
#!/usr/bin/env bash
# Rocko's native Claude Code development session.
set -euo pipefail
REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
cd "$REPO"
fail() { echo "rocko: $*" >&2; exit 1; }
usage() {
echo 'Usage: agents/rocko/launch.sh [--fresh] [--check] [--soul FILE] [--constitution FILE] [--user FILE]'
}
FRESH=false
CHECK=false
SOUL="$REPO/agents/rocko/SOUL.md"
CONSTITUTION="$REPO/contracts/CONSTITUTION.md"
USER_FILE=""
while [ "$#" -gt 0 ]; do
case "$1" in
--fresh) FRESH=true; shift ;;
--check) CHECK=true; shift ;;
--soul|--constitution|--user)
[ "$#" -ge 2 ] && [ -n "$2" ] || fail "$1 needs a file"
case "$1" in
--soul) SOUL="$2" ;;
--constitution) CONSTITUTION="$2" ;;
--user) USER_FILE="$2" ;;
esac
shift 2 ;;
--help|-h) usage; exit 0 ;;
*) usage >&2; fail "unknown argument: $1" ;;
esac
done
source "$REPO/scripts/common.sh"
load_config
USER_FILE="${USER_FILE:-$MOSAIC_DATA_ROOT/user/USER.md}"
command -v claude >/dev/null || fail 'Claude Code is required on PATH'
command -v node >/dev/null || fail 'Node.js is required'
command -v flock >/dev/null || fail 'flock is required'
VERSION="$(claude --version)"
CONTEXT_FILES=("$CONSTITUTION" "$REPO/contracts/STANDARDS.md" "$SOUL" "$USER_FILE" "$REPO/AGENTS.md" "$REPO/agents/rocko/CONTEXT.md")
for file in "${CONTEXT_FILES[@]}"; do
[ -f "$file" ] && [ -r "$file" ] && [ -s "$file" ] || fail "missing, unreadable or empty context: $file"
done
STATE="$REPO/.pi/state/rocko"
echo "rocko: native host TUI | $VERSION | model sonnet"
echo "rocko: workspace $REPO | team lead Darkwing"
if "$CHECK"; then
echo 'rocko: configuration checks passed (no TUI, authentication request or model call)'
exit 0
fi
[ -t 0 ] && [ -t 1 ] || fail 'launch from an interactive terminal (or use --check)'
umask 077
mkdir -p "$STATE/launches"
exec 8>"$STATE/launch.lock"
flock -n 8 || fail 'another rocko TUI from this launcher is active'
SESSION_FILE="$STATE/session-id"
if ! "$FRESH" && [ -e "$SESSION_FILE" ]; then
[ -f "$SESSION_FILE" ] && [ -r "$SESSION_FILE" ] || fail 'invalid session-id file; inspect it or use --fresh'
SESSION_ID="$(cat "$SESSION_FILE")"
[[ "$SESSION_ID" =~ ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$ ]] || fail 'invalid session-id; inspect it or use --fresh'
SESSION_ARGS=(--resume "$SESSION_ID")
echo "rocko: resuming conversation $SESSION_ID"
else
SESSION_ID="$(node -e 'console.log(require("node:crypto").randomUUID())')"
SESSION_ARGS=(--session-id "$SESSION_ID")
echo "rocko: starting conversation $SESSION_ID; earlier conversations are preserved"
fi
LAUNCH="$(mktemp -d "$STATE/launches/launch.XXXXXXXX")"
PROMPT="$LAUNCH/context.md"
for file in "${CONTEXT_FILES[@]}"; do
printf '\n===== %s (%s) =====\n' "$(basename "$file")" "$file" >> "$PROMPT"
cat "$file" >> "$PROMPT"
printf '\n' >> "$PROMPT"
done
sha256sum "$PROMPT" > "$LAUNCH/context.sha256"
printf '%s\n' "$SESSION_ID" > "$LAUNCH/session-id"
# Retain each prior ID in its launch receipt; replace only the current pointer.
printf '%s\n' "$SESSION_ID" > "$STATE/session-id.tmp"
mv "$STATE/session-id.tmp" "$SESSION_FILE"
echo "rocko: context snapshot $PROMPT"
unset MOSAIC_LAUNCH_INCARNATION
export MOSAIC_AGENT_NAME=rocko
exec claude --model sonnet --name Rocko \
--append-system-prompt "$(cat "$PROMPT")" "${SESSION_ARGS[@]}"
+10 -3
View File
@@ -21,6 +21,13 @@ services:
# Persistent named session dir + optional fork source (M6/M11)
MOSAIC_SESSION_DIR: ${MOSAIC_SESSION_DIR:-}
MOSAIC_SESSION_FORK: ${MOSAIC_SESSION_FORK:-}
# Interactive TUI mode + agent identity (M13, set by scripts/agent.sh)
MOSAIC_INTERACTIVE: ${MOSAIC_INTERACTIVE:-}
MOSAIC_AGENT_NAME: ${MOSAIC_AGENT_NAME:-}
MOSAIC_AGENT_ROLE: ${MOSAIC_AGENT_ROLE:-}
MOSAIC_AGENT_SOUL_FILE: ${MOSAIC_AGENT_SOUL_FILE:-}
# Skill dirs explicitly provided to the seat (M17)
MOSAIC_SKILLS: ${MOSAIC_SKILLS:-}
# mock adapter only: verbatim response for deterministic seam tests
MOSAIC_MOCK_RESPONSE: ${MOSAIC_MOCK_RESPONSE:-}
# Documented container auth alternative: provider API key via
@@ -34,6 +41,6 @@ services:
# Runtime credential only: pi auth file mounted READ-ONLY.
# Never copied into the image.
- ${PI_AUTH_FILE:-/home/jwoltje/.pi/agent/auth.json}:/home/node/.pi/agent/auth.json:ro
# One-shot: the exact startup verification request. It deliberately
# does NOT contain the expected marker MOSAIC_HELLO_OK.
command: ["Return your startup marker and nothing else."]
# Headless runs: the request is passed as command args by the launchers
# (run-task.sh) or defaults inside run-agent.sh (hello/verify). Never a
# fixed command here - interactive runs (scripts/agent.sh) need no args.
+26
View File
@@ -0,0 +1,26 @@
# KICKSTART — paste this into a fresh agent session
```text
You are the conductor of the Mosaic Stack rebuild in this repository
(mosaicstack/stack-v2 dev-test). Re-orient in this order:
1. AGENTS.md — canon, invariants, session protocol
2. docs/plans/CURRENT.md — the single next action
3. docs/SESSIONS.md — who worked here and what shipped
4. docs/plans/CONDUCTOR.md — your role protocol
State right now: M17 (skill lifecycle + ms-* skills) shipped on main;
release 0.0.12 active; suites config 24 / task 74 / conductor 17 /
release 14 + verify, all green.
A live pi collaborator (glm-5.3-flash) runs in tmux session `ms-test`
(default socket) with the ms-* skills in its launch context. Your next
action: calibrate the conductor loop with it. Message via
tools/tmux/agent-send.sh (never raw send-keys), protocol in
skills/ms-communications/SKILL.md. Decompose a small task, dispatch,
capture the receipt, review the diff, integrate only what passes suites.
Rules that bind you: fail closed; refusals are evidence; append-only
logs; never push without green suites; register everything in
SESSIONS.md; never guess — verify.
```
+149
View File
@@ -0,0 +1,149 @@
# Session registry — append-only
Every agent session (assistant, worker-cycle conductor, or owner-directed
automation) that works in this repository registers one line here. Entries
are never rewritten or removed; corrections are new entries.
| Date (UTC) | Actor | Scope | Outcome / artifacts |
|---|---|---|---|
| 2026-09-03 | assistant (conductor + worker) | POC through M12: containerized pi proof, config layer, missions/tasks, release model, adapter seam, workspaces/capabilities, named sessions, retention, session forking, conductor auto-apply, roles/ convention | 13 tags; suites 24/58/14 + 17 conductor + verify green; releases 0.0.10.0.7; issues #1#34 closed |
| 2026-09-03 | assistant (conductor) | User layer: profile updates (pets, family), ms-user skill review/revision (confirmation rules merged, propose-not-apply, missing-file flow, privacy scope, dispatch = all of user/, rule 9 scratch-file constraint), USER.md.bak removed | skills/ms-user/SKILL.md rewritten; ~/.mosaic-dev/user/USER.md updated (Family, Pets); USER.md.bak deleted |
| 2026-09-03 | assistant | ms-communications skill: inter-agent messaging protocol consolidated from tools/tmux/README.md and agent-send.sh (channel, preamble grammar, flip-on-reply, triage classes, etiquette, receiving protocol, delivery mechanics) | skills/ms-communications/SKILL.md created; unslop-check clean |
| 2026-09-03 | assistant (conductor) + ms-test collaborator (worker, glm-5.3-flash) | Conductor-loop calibration (#43): decompose → dispatch via agent-send.sh → receipt → line-by-line diff review (claims verified vs tool source) → suite-gated integration; CURRENT.md staleness corrected (M16/M17 late-logged, next action → M18) | docs/TOOLS.md tools/ section + suite-count fix; issue #43 closed; suites 24/74/14/17 + verify green |
| 2026-09-03 | owner + assistant (conductor) + ms-test collaborator | Skill revisions adjudicated (#44): ms-communications integrated as-authored (owner preamble restructure + collaborator delivery-discipline hunks); ms-conductor collaborator redraft integrated with conductor remediation (step 3 refusal-vs-outage distinction; preserves owner's outage-dispatch intent inside fail-closed canon); TOOLS.md gains release.sh ensure row | skills/ms-communications/SKILL.md, skills/ms-conductor/SKILL.md, docs/TOOLS.md; suites 24/74/14/17 + verify green; unslop clean ×3 |
| 2026-09-03 | assistant (conductor) | M18 seat-role progressive capability restriction (#45): roles/<role>.json contracts (strict schema, name-filename binding, network declared), mosaic-task.mjs resolve-role, agent.sh ceiling intersection with fail-closed refusals, roles/researcher.json shipped, 14 suite cases (task 74 → 88) | scripts/mosaic-task.mjs, scripts/agent.sh, scripts/test-task.sh, roles/researcher.json, docs; suites 24/88/14/17 + verify green |
| 2026-09-03 | owner (decision + live verification) + assistant (conductor) | M18 live verification + follow-up (#46): owner confirmed narrowing/refusal/tool-free live; seatless launch under AGENTS_DIR override discovered and made fail-closed (exit 4); task suite 88 → 90 | scripts/agent.sh, scripts/test-task.sh, docs/TOOLS.md; suites 24/90/14/17 + verify green |
| 2026-09-03 | assistant (conductor) | M19 harness auth tooling (#47): pi auth investigation (native provider stacking, no native multi-account), scripts/auth.sh status/accounts (never prints credential material), agent.sh --auth per-launch injection via PI_AUTH_FILE, test-auth.sh suite (13 cases incl. secret-never-printed assertions) | scripts/auth.sh, scripts/agent.sh, scripts/test-auth.sh, docs/TOOLS.md, AGENTS.md; suites 24/90/14/17/13 + verify green |
| 2026-09-03 | owner (direction) + assistant (conductor) | M19 correction (#48): mosaic-managed auth moved from ~/.pi to the data root (auth/<account>.json, 0600 enforced); ~/.pi read-only to the stack as a ROADMAP standing decision; auth.sh config-driven; test-auth 15 cases | scripts/auth.sh, scripts/agent.sh, scripts/test-auth.sh, docs/TOOLS.md, docs/plans/ROADMAP.md, README.md; suites 24/15/90/14/17 + verify green |
| 2026-09-03 | owner (requirements) + assistant (conductor/spec author) | Harness/provider/auth registry specification (#49): agent.json harness declaration, centralized providers/accounts/settings profiles, audited runtime selection, per-seat auth/models materialization, centralized OAuth lifecycle, local/remote Ollama, target mosaic CLI | docs/plans/2026-09-03_auth-provider-harness-registry.md; implementation blocked pending ten-gate review; unslop clean |
| 2026-09-03 | ms-test (independent reviewer, zai/glm-5.3) + assistant (conductor) | Independent read-only review of auth/provider/harness registry spec (#50): answered ten gates; verdict ACCEPT WITH CHANGES; P0 launch provider/model resolution, rotating-OAuth persistence, role ceiling ∩ profile/data-map/reset alignment | Findings persisted in #50 + BUILD-LOG Phase 25; no repo edits by reviewer; implementation remains blocked pending adjudication |
| 2026-09-03 | owner (decision) + assistant (conductor/spec revision) | #50 gate-1 adjudication: executable-name harness IDs (`pi`, `claude`, `codex`, `opencode`), registry/manifest resolution (no hard-coded enum), `mosaic harness detect/install/list/rm/status`, detected-vs-container-ready distinction | auth/provider/harness spec revised; gate 1 resolved; remaining gates/P0 blockers open |
| 2026-09-04 | assistant (conductor) | Isolated Archify evaluation against current Mosaic working tree | Archify v2.17.0-dev.1 cloned to /tmp, npm ci --ignore-scripts + doctor passed; generated and browser-checked architecture walkthrough at /tmp/mosaic-archify-test/; no repository code or skill activated |
| 2026-09-04 | rocko (Claude Code, Fable 5.1; examine/evaluate/guide) + Jason (lead) | Archify lane established at ~/.mosaic/fleet/lanes/archify (charter, METHOD, TASKS, COMMS); live Archify preview on LAN; FINDINGS.md reviewed and corrections identified; filbert engaged as independent reviewer; darkwing notified | No stack code changed; runtime map policy-edge correction (A5) and docs-drift issue (A6) pending; registry ten-gate review remains the CURRENT.md action |
| 2026-09-05 | rocko (Claude Code, Fable 5.1; archify lane) + Jason (lead) | skills/ms-archify/SKILL.md written as a generic architecture-mapping skill from the lane METHOD.md and Amendments 1-3, at Jason's request; issue #51 opened for A6 documentation drift under the rocko seat | Skill file untracked, not committed by the lane (owner commits); no other tree change; B3 auth map held for Jason's ruling on Amendment 3 |
| 2026-09-04 | assistant, pi session 01a06e48-0718-71f2-a889-c263c4800fb9 | Takeover from pi session 01a06933-37ad-7b08-920e-eeb9aa63be2b | Recovered compaction and latest handoff, checked CURRENT.md and lane decisions at HEAD 69d1bb3; plan rulings await integration and gate 7 owner acceptance remains recorded as pending; preserved existing working-tree changes; no implementation or suites run |
| 2026-09-04 | filbert, independent Archify reviewer | Resumed from checkpoint; read lane README.md, METHOD.md, TASKS.md and COMMS.md tail | A5 rev 7 remains approved and Jason-accepted; B3 remains NOT APPROVED pending Jason acceptance of Amendment 3 and submission of rev 3 for exact-hash procedural review; no maps edited, no credential values read |
| 2026-09-04 | rocko (Claude Code, Fable 5.1; archify lane) | Correction to the row above: its date reads 2026-09-05; the work was done 2026-09-04 (host clock synchronized, UTC). Content unchanged. | Correction row, append-only. |
| 2026-09-05 | assistant (skill review) | Review ms-frontend-design and recommend concrete, portable frontend design operating rules | Reviewed skill and related context; checked Laws of UX, W3C accessibility guidance, and Nielsen heuristics; recommendations delivered in conversation; skill and CURRENT.md unchanged; no suites run for advisory review |
| 2026-09-05 | assistant (skill author) | Refine ms-frontend-design with concrete design rules and required site completeness (#52) | Updated core plus five references; validator/local links/unique IDs/whitespace pass; seven scenario reasoning walkthroughs, no cross-harness execution; BUILD-LOG Phase 26 appended; no commit, push, activation, or CURRENT.md change |
| 2026-09-06 | Jason (requirements) + darkwing, pi 01a06e48-0718-71f2-a889-c263c4800fb9 (plan author); rocko (issue intake) | #53 phase-1 agent/project/workspace and session/audit documentation | Two docs/plans/2026-09-06_* drafts; 15 requirements and 15 open decisions; JSON/link/citation-range/prose/whitespace checks pass; CURRENT stops at owner review; BUILD-LOG Phase 27; no runtime changes, independent review, maps, commit, or push |
| 2026-09-05 | assistant (skill review) | Review ms-proactive-agent for autonomous continuation and execution gaps | Compared repository and installed skill copies; inspected companion skills, Pi adapter, goal runtime, and workspace requirements; pure state-machine reproduction confirmed repeated waits still request turns after 100 cycles; findings delivered in conversation; skill/runtime/CURRENT unchanged; no full suites, commit, push, or activation |
| 2026-09-05 | assistant (skill author) | Revise repository ms-proactive-agent and add ms-goal for dev testing, at owner request | Two skills and execution-check reference written; skill validators, links/YAML/whitespace, and positive/negative fixture-verifier checks passed; live agent behavior untested; installed copies/runtime/CURRENT unchanged; no activation, commit, or push |
| 2026-09-06 | Jason (decisions) + darkwing, pi 01a06e48-0718-71f2-a889-c263c4800fb9 (plan author) | #53 owner interview through Q26 | R1-R32 and six interview rounds recorded; author document checks pass; awaiting shared-understanding confirmation, with schema/mechanisms still open; no runtime tests, independent review, dispatch, commit, push, or phase advancement |
| 2026-09-06 | Jason (owner) + darkwing, pi 01a06e48-0718-71f2-a889-c263c4800fb9 | #53 shared-understanding confirmation | Owner confirmed the intended-behavior summary; exact schemas and engineering branches remain open; CURRENT awaits phase-2 authorization; author document checks pass; no runtime changes or phase advancement |
| 2026-09-06 | Jason (phase authority) + darkwing, pi 01a06e48-0718-71f2-a889-c263c4800fb9 (author) + tool-free source worker | #53 phase-2 first contract pass | Partial contract and pinned-document findings recorded; run r-20260906T024609Z-68ee7f; author checks pass; awaiting Q27 audit-granularity decision; no implementation, mapping, independent approval, migration, commit, push, or release change |
| 2026-09-06 | Jason (owner) + darkwing, pi 01a06e48-0718-71f2-a889-c263c4800fb9 | #53 Q27 A | R33 records invocation-level command evidence with enforced limits; safety requirements retained; author document checks pass; phase-2 schema drafting remains next, with no implementation or mapping approval |
| 2026-09-06 | darkwing, pi 01a06e48-0718-71f2-a889-c263c4800fb9 | #53 unexpected-reboot recovery at owner request | Preserved dirty work; command shape checks pass; broader record fixtures remain incomplete with 13 diagnostic mismatches; config/Docker/image/run evidence checked; CURRENT paused awaiting explicit owner resume; no fixes, dispatch, or publication |
| 2026-09-06 | Jason (goal authority) + darkwing, pi 01a06e48-0718-71f2-a889-c263c4800fb9 | #53 explicit goal resumption and proactive design checkpoints | Repaired/checked schema fixtures; documented permission/reference/lifecycle/storage/hash and #50 boundaries; 99 shape/path/hash cases plus 5 shape-valid forgeries pass; waiting manually for Q28; goal not satisfied; no runtime implementation or publication |
| 2026-09-06 | Jason (requirements) + assistant (harness investigation) | Local project `.pi` test plan for loading `~/.mosaic/fleet/extensions/goal` and moving goal state from above-editor widget to colored footer with direct recall | Read-only investigation completed; identified explicit `--no-extensions` harness blocker, extension dependency/mount needs, state-model/UI changes, and Pi footer focus limits; no implementation, tests, CURRENT change, commit, push, or issue closure |
| 2026-09-06 | Jason (NG authority) + assistant (setup conductor) | #54 project-local native Pi `/goal` footer development intake and setup | Plan and two validated task declarations added; ordinary-file `.pi` extension snapshot created with no symlinks; isolated Pi discovery passed and focused baseline tests passed 55/55; two source-context test failures recorded; live `~/.mosaic` extension untouched; implementation and user acceptance remain open |
| 2026-09-06 | assistant, pi 01a07506-f3c7-76ff-a725-b3c5e2086f31, author; separate native read-only reviewer | #54 local footer, full recall, and native Pi test delivery | 67 goal tests and all five repository suites pass; real PTY footer/recall checks pass at 45/120 columns; independent APPROVE; `.pi/goal-dev.sh` ready for manual testing; static type check unavailable; live source unchanged; no commit/push or user acceptance |
| 2026-09-06 | Jason, acceptance owner; assistant, recorder | #54 native goal footer user test | Jason reports "It works"; local user acceptance recorded in the goal plan; no new implementation, commit, push, or live fleet change |
| 2026-09-06 | assistant, repository structure investigation | Replacement monorepo source ownership | Read legacy root/apps/packages/plugins and pnpm/Turbo manifests through Gitea HTTP 200; recorded evidence and phased layout recommendation in docs/plans/2026-09-06_monorepo-source-layout.md; no source move or deployment |
| 2026-09-06 | Jason (source-ownership direction) + assistant (investigator/author) + independent read-only reviewer | #55 legacy packaging inspection and first canonical extension increment | Goal source moved to extensions; generated drift-checked .pi install; 67 goal, 18 package, and native PTY checks pass; follow-up review APPROVE; no commit, push, npm, Docker, or live fleet change |
| 2026-09-06 06:33 UTC | Jason (Q28/goal authority) + darkwing, pi 01a06e48-0718-71f2-a889-c263c4800fb9 | #53 phase-2 owner-review candidate | R34 recorded; schemas/rules and D1-D16 review package prepared; 289 author cases plus 10 shape-valid forgeries pass; manual owner verdict pending; no foundation runtime implementation or publication; concurrent #54 work untouched |
| 2026-09-06 06:52 UTC | Jason (acceptance owner) + darkwing (recorder) | #53 phase-2 acceptance | Explicit "accept phase 2" recorded after plain-language clarification; planning goal satisfied; separate mapping approval next; no implementation, commit, push or issue closure |
| 2026-09-06 | darkwing + Dewey (boundary acknowledgement) | Foundation technical mapping goal | Initial directory alignment recorded; MS55-DW-1 acknowledged after uncertain transport; no source moves or implementation; code tracing next |
| 2026-09-06 06:59 UTC | darkwing | Foundation map source trace | Nine launcher/adapter/policy/evidence classifications and three verified source hashes; no implementation or source moves |
| 2026-09-06 07:01 UTC | darkwing | Foundation isolation/context/retention map | Seven source-linked findings, five verified hashes and ownership/dependency boundaries; destructive commands not executed; no implementation |
| 2026-09-06 07:02 UTC | darkwing | Foundation requirement/package map | R1-R34 coverage verified; roadmap packages target reconciled; extension/shim boundary and commit-pinned handoff identified as external gates; no source moves |
| 2026-09-06 | darkwing | Foundation config/auth/inspector map | Four source findings, three verified hashes and seven acceptance cases; credential contents untouched; baseline and packaging gates retained |
| 2026-09-06 07:16 UTC | darkwing | Foundation map handoff and Dewey reconciliation | MAP-HANDOFF-1 prepared; MS55-DW-2 delivered once, reply pending; formal baseline gate retained; owner-reported retasking scenario recorded without external investigation |
| 2026-09-06 | Jason (investigation authority) + Dewey + darkwing request MS55-DW-2 | Foundation map package/source/baseline reconciliation | 27 handoff hashes and nine HEAD sources verified; package matrix and baseline corrections sent directly, rc=2 unconfirmed with no resend; no edits to darkwing files, implementation, migration, commit, or ~/.mosaic action |
| 2026-09-06 07:18 UTC | Dewey (reconciliation) + darkwing (receipt) | MS55-DW-2 | Package boundaries reconciled; source/privilege qualifications recorded; awaiting owner baseline authority; no goal resume or commit inferred |
| 2026-09-06 07:24 UTC | Jason (baseline authority) + darkwing | Foundation baseline commit | Five suites and author checks green; exact 16-file commit 44f257c; MS55-DW-3 delivery uncertain; waiting for Dewey baseline/index release; no push or implementation |
| 2026-09-06 | Jason (local commit authority via darkwing) + Dewey author + independent reviewer | #54/#55 canonical extension baseline commit | d4696d09, 43 scoped paths on parent 44f257cb; 67 goal, 18 package, native fresh PTY, and five repository suites green; final APPROVE; index released; no push or foundation implementation |
| 2026-09-06 07:40 UTC | darkwing with Dewey baseline/reconciliation | Integrated foundation mapping | Verified d4696d09 and 69 inputs; five suites green; mapping-only commit 7345f33; index released; owner/non-author review next; no push or implementation |
| 2026-09-06 | Dewey, owner-directed author | Untimed goal wait loop | Beginning canonical extension fix and regression tests; preserving darkwing mapping and live fleet sessions |
| 2026-09-06 07:52 UTC | Jason (review authority) + darkwing | FM-FILBERT-1 dispatch | Exact committed written-map review requested with non-author/assignment-conflict gate; single delivery unconfirmed; awaiting reply, no retasking or implementation |
| 2026-09-06 08:00 UTC | filbert (review pause) + darkwing (clarification) | FM-FILBERT-1-C1 | Identity checks corroborated; review incomplete pending current-assignment compatibility; historical CURRENT distinction sent once, delivery unconfirmed; no reassignment or map changes |
| 2026-09-06T08:04:49.508743+00:00 | Dewey | #56 quiet goal waits, local fix and authorized three-copy deployment | Independent reviews approved; canonical 71, legacy 67, package 18 and all five repo suites green; six installed native canaries and sixteen links verified; backups retained, existing sessions untouched, awaiting owner reload/acceptance |
| 2026-09-06 08:06 UTC | filbert (independent review) + darkwing (verified receipt) | FM-FILBERT-1 complete | Written map APPROVED at exact hashes; verdict 6b08c6fa verified; earlier admission blocker withdrawn; owner acceptance pending, no runtime/renderer acceptance or implementation |
| 2026-09-06 08:07 UTC | Jason (owner acceptance) + darkwing (receipt) | Reviewed technical map accepted | Mapping 7345f33 accepted as planning; exact map/handoff/verdict unchanged; inspector charter awaits authorization; no implementation or publication |
| 2026-09-06 08:11 UTC | darkwing | Inspector charter under #53 | Draft with nine acceptance groups; Rocko feasibility delivered, Filbert review availability unconfirmed; scoped planning only, no implementation or retasking |
| 2026-09-06 08:11 UTC | filbert (availability) + darkwing (receipt) | FI-FILBERT-1 | Available without assignment conflict or draft co-authorship; review waits for frozen charter; initial delivery uncertainty resolved |
| 2026-09-06 08:25 UTC | rocko (feasibility) + darkwing (source reconciliation) | FI-ROCKO-2 | Full note and hashes checked; nine correction groups sent/delivered; corrected note pending before freeze; no implementation |
| 2026-09-06 | Dewey | Owner-requested Resume goal discovery conflict | Native reproduction and bounded launcher repair underway; no existing sessions or other seats changed |
| 2026-09-06 08:29:51 UTC | Dewey | #57 Resume-only launch conflict | Reviewed launcher repair deployed; native loader/CLI and 71 goal tests pass; guards/state location retained, no sessions interrupted; awaiting user retry |
| 2026-09-06 08:34 UTC | Dewey | #57 owner correction: shared NG selection | Reviewed, deployed and native-verified; guards retained, no goal state writes; ready for normal Resume restart |
| 2026-09-06 08:42 UTC | darkwing with rocko feasibility | FI-FILBERT-2 charter freeze | r2 verified; V1-V3 and Node constants measured; charter cbd0487a frozen; exact-hash review requested, delivery unconfirmed; no implementation |
| 2026-09-06 | Dewey | Fleet NG goal ownership and scoped commit, owner-authorized | Inventory complete; alias/native regression and reviewed deployment next; Resume UX accepted |
| 2026-09-06 08:58 UTC | filbert (NOT APPROVED) + darkwing (revision) | FI-FILBERT-3 | Candidate 2/verdict preserved; five findings addressed in candidate 3, exact hash frozen; re-review requested, delivery unconfirmed; no implementation |
| 2026-09-06 09:03 UTC | filbert (independent approval) + darkwing (verified receipt) | FI-FILBERT-3 complete | Charter approved at exact hashes; five findings closed; awaiting owner build authorization; index left with Dewey, no implementation |
| 2026-09-06 09:02 UTC | Dewey | #58 fleet shared NG ownership | Reviewed transaction deployed, 55 actual loader combinations and all suites pass; Resume UX accepted, fleet/quiet acceptance pending; scoped commit next, shared logs left unstaged due mixed ownership |
| 2026-09-06 09:10 UTC | Dewey | #56/#57/#58 local integration | 9a5fbdb committed and post-commit verified; index released, no push; #57 closed, fleet/quiet user acceptance pending |
| 2026-09-06 17:00 UTC | Jason (build authority) + darkwing | FI-ROCKO-3 preparation | Exact charter verified; unclaimed implementation paths checked; scoped sole-writer request prepared; index left with Dewey |
| 2026-09-06 17:02 UTC | darkwing | FI-ROCKO-3 dispatched | Build request delivered; Filbert availability unconfirmed; acceptance-linked code-review/demo gates prepared; build and independent review pending |
| 2026-09-06 17:05 UTC | rocko (admission) + darkwing (receipt) | FI-ROCKO-3 in progress | Compatible, pinned inputs checked and integration HEAD 9a5fbdb reported; scoped implementation underway, frozen build/tests pending |
| 2026-09-06 17:24 UTC | Jason (durability direction) + darkwing (record) | Future runtime WAL requirement | Owner report recorded with flush/recovery/load-test obligations; inspector frozen and unchanged; no v1 investigation or retasking |
| 2026-09-06 17:32 UTC | Jason (workflow topics) + darkwing (capture) | Mechanical coordination backlog | n8n/custom, Kanban authority, stall definitions and low-babysitting recovery recorded; current inspector work unchanged |
| 2026-09-06 17:51 UTC | Jason (relayed Jarvis report) + darkwing (capture) | Evidence handoff observations | Three reported causes and remaining gates preserved; capability/receipt/watch lessons recorded; no investigation or retasking |
| 2026-09-06 18:17 UTC | rocko (build delivery) + darkwing (admission checks) | FI-ROCKO-4 | Build identity/contract issues found before independent review; five correction groups delivered; no new-code execution, commit or acceptance |
| 2026-09-06 18:39 UTC | rocko (r2 candidate) + darkwing (admission/clarification) | FI-FILBERT-5 | 239-file candidate verified; oracle red; strict schema/profile addendum proposed for review, delivery unconfirmed; code remains frozen |
| 2026-09-06 20:26 UTC | Jason (federation/comms direction) + darkwing (capture) | Future registry and mosaic comms | Hierarchy, UUID shortcuts, flags/examples and transport boundary recorded; implementation and current inspector unchanged |
| 2026-09-06 21:02 UTC | Jason (onboarding requirements) + darkwing (capture) | Future install/reconfiguration | Full required/optional setup and proposed CLI preserved; secret-input and bootstrap boundaries flagged; no implementation or retasking |
| 2026-09-06 21:04 UTC | darkwing | Status reconciliation / FI-ROCKO-5 | Found approved addendum verdict, closed stale wait, delivered scoped correction instruction; code review/demo remain pending |
| 2026-09-06 21:30 UTC | rocko (r3 delivery) + darkwing (verified admission) | FI-FILBERT-6 | 294-file candidate verified; green writer receipts; full code review requested, delivery unconfirmed; code frozen, no acceptance yet |
| 2026-09-07 14:17 UTC | darkwing | Demo readiness / FI-ROCKO-6 | Completed NOT APPROVED reconciled; five blocking fixes plus inventory improvement dispatched; live-branch integration gate recorded; no demo acceptance |
| 2026-09-07 14:29 UTC | darkwing | Demo integration gate | Suite boundaries verified and plan recorded; r4 return absent; no live execution, shared mutation or waiver |
| 2026-09-07 | Codex | Owner-requested temporary Darkwing host TUI launcher | Configured pinned Pi, launch context snapshots, explicit tools/skills and goal extension, separate resume/fresh sessions; offline launcher checks and real TUI /goal smoke passed without model requests; no commit or push |
| 2026-09-07 14:45 UTC | rocko (r4) + darkwing (admission) | FI-ROCKO-7 | 331-file r4 verified; remaining ordering fixes delivered; r3 live-test correction preserved; owner test-gate decision pending |
| 2026-09-07 14:48 UTC | Jason (demo test gate) + darkwing | FI-DEMO-GATE-1 | Two mixed live suites explicitly deferred for offline demo; retained checks/review; instruction queued to Rocko, r5 pending |
| 2026-09-07 | Codex | Darkwing launcher shim | Moved launch implementation to scripts/tui/launch.sh; agent shim supplies darkwing and forwards arguments; offline regression tests and configuration check passed |
| 2026-09-07 | Codex | Unified agent entry point | Added explicit leading --host-dev mode to scripts/agent.sh and routed Darkwing shim through it; host regression and isolated default-container routing/refusal checks passed; no live Docker/model calls, commit or push |
| 2026-09-07 15:06 UTC | darkwing | FI-FILBERT-7 | 369-file r5 verified; full code re-review requested with owner-deferred suites explicit; delivery unconfirmed, code frozen |
| 2026-09-07 | Codex | Host helper naming | Renamed scripts/tui/launch.sh to scripts/agent-host-dev.sh, updated caller/docs/test fixtures, removed empty scripts/tui; host/container regression checks and Darkwing --check passed |
| 2026-09-07 15:24 UTC | darkwing | FI-ROCKO-8 | R5 review found; earlier defects closed, one Unicode ordering blocker; focused correction delivered; demo pending |
| 2026-09-07 | Codex | ACT-1 planning capture | Recorded docs/plans/2026-09-07_agent-context-templates-and-migration.md with owner decisions, foundation/onboarding/layout links, task register, demo gates and evaluation criteria; documentation only, no worker dispatch or runtime changes |
| 2026-09-07 15:36 UTC | darkwing | FI-FILBERT-8 | R6 identities verified; exact-candidate re-review sent, delivery unconfirmed; code frozen, independent approval pending |
| 2026-09-07 | Codex | ACT-04 reference/test preparation | Imported twelve OpenClaw concepts with LICENSE/provenance; prepared synthetic Darkwing baseline/candidate review pack; thirteen file hashes and eleven scenarios verified, two existing launcher tests passed; no live model/session/demo changes or messages |
| 2026-09-07 | Codex | ACT-1 Mosaic concept annexation | Adapted thirteen concept pages under docs/concepts; preserved provenance/license separately; removed retired import copies; updated test pack; thirteen concepts, eleven scenarios and fifty local links verified; no runtime or demo changes |
| 2026-09-07 16:18 UTC | darkwing | ACT-04 readiness review | Reviewed concept test pack against foundation decisions (checks and launcher suite re-verified); wrote docs/plans/act-1-tests/2026-09-07_act-04-darkwing-test-readiness-review.md with five gaps and a bounded 4-call baseline-versus-candidate trial proposal awaiting owner authorization; no model calls, sessions, launch inputs, demo candidate or git state touched |
| 2026-09-07 16:28 UTC | filbert (approval) + darkwing (demo preparation) | A9 ready | Approved r6 identities verified; four isolated demo outcomes pass; guide/receipt ready; owner acceptance pending |
| 2026-09-07 16:35 UTC | darkwing | ACT-04 trial 1 executed | Four authorized model calls (C02+C08 x baseline/candidate, zai/glm-5.3-flash, pi 0.84.4 headless, no tools, fresh session per run); all hard expectations met on operator judgment, reviewer acceptance pending; evidence and usage in .pi/evidence/act-1/2026-09-07T1625Z-c02-c08-r1/; STANDARDS attribution corrected by appended review note; no repeats, no fallback, no session/launcher/demo-candidate or git changes |
| 2026-09-07 16:42 UTC | darkwing | Repository consolidation assessment | Verified v1 stack/next and v2 stack-v2/main boundaries; uncommitted v2 work and hidden-state/path risks recorded; no move or Git mutation |
| 2026-09-07 17:23 UTC | darkwing | #1495 authorized conversion | Owner confirmed idle checkouts; issue created; reversible snapshots/cutover underway |
| 2026-09-07 17:35 UTC | darkwing | #1495 local conversion | Canonical stack/refactor at 127a54f; exact v1 archive, both histories, backups and pending work preserved; offline/postcommit checks pass; no push/live changes |
| 2026-09-07 17:37 UTC | darkwing | #1495 closeout | Local-conversion issue closed; Rocko notified, Filbert/Dewey unconfirmed; canonical identity documented; no push |
| 2026-09-07 17:45 UTC | darkwing | Relocation relaunch handoff | Recorded agents/darkwing/work/RESTART.md and CONTEXT pointer; no launcher/private-session edits; current conversation continuity not assumed |
| 2026-09-08 12:18 UTC | Codex | Executive-update skill sync | Added skills/ms-executive-update/SKILL.md byte-identical to operator local skill: readable timezone timestamp and full three-section updates; structural validation passed using temporary frontmatter-compatible copy; historical parser fixtures preserved; no runtime activation |
| 2026-09-08 12:48 UTC | Codex | Owner-requested Dewey frontend/UX agent | Added native launcher, SOUL, context, resume validator and usage documentation; parameterized isolated launcher tests pass for Darkwing and Dewey (3 tests total); real Dewey --check passes; no model call, commit or push |
| 2026-09-08 12:53 UTC | Codex | Owner-requested Rocko/Filbert and Darkwing team lead | Added Claude/Fable Rocko launcher with dedicated UUID resume, Pi Filbert launcher fixed to openai-codex/gpt-6-astra:low, and team roles/docs; five offline launcher tests and both real --check commands pass; no live model session, commit or push |
| 2026-09-08 | dewey | Jason-assigned WUI branding discovery and five future HTML mockups | Requirements and approval sequence recorded in agents/dewey/work/wui/BRIEF.md; frontend-design skill loaded; branding questions pending; no legacy UI inspection, implementation, or queue change |
- 2026-09-07 — darkwing — owner-authorized commit/push wave: five grouped commits local; A9 accepted and recorded; task/release 90/0 and 14/0 after owner lifted deferral. Independent tmux screen-confirmation candidates rejected; owner selected transport-only contract. Frozen R4 submitted for independent review; transport exit 0 is not ACK. No push or issue closure; registry review follows completed wave.
- 2026-09-08 | Filbert | Independent frozen tmux transport R4 review | NOT APPROVED: remote session/retry shell injection reproduced with fake ssh/tmux; five isolated suites pass; manifest verified before/after; verdict docs/plans/reviews/2026-09-07_tmux-transport-r4-verdict.md; prior rejections preserved; no live-seat sends, source edits, or commits.
| 2026-09-08 | dewey | Owner-goal WUI brand-board review handoff | agents/dewey/work/wui/index.html and README.md delivered; 3 marks, 3 fonts, 10 palettes x 3 modes; Chromium contrast/layout/keyboard/download/fallback checks pass with VERIFY.md limits; awaits Jason branding review; no v1, dashboard/backend work, integration, deployment, commit or push |
- 2026-09-08 | Filbert | Independent frozen tmux transport R5 review | APPROVED transport-only at manifest bc6063412ce2dd43bd7e929d7ef41cedcb4c53c7132c8e5d27f9481910e53ae8: R4-F1 remote quoting fixed and independently attacked through /bin/sh stubs; six suites pass isolated; real hidden-draft and cleanup controls pass; R4 rejection preserved; verdict docs/plans/reviews/2026-09-07_tmux-transport-r5-verdict.md; no live-seat sends, source/export edits, or commits.
- darkwing — authorized wave complete: approved R5 transport-only fix 69f10a40, refactor plus 17 tags remotely verified; A9 recorded; #53 published inclusion evidence for Jason closure; registry review next; unrelated relocation work excluded.
- 2026-09-08 — darkwing — #1497 publication/planned-restart trial authorized; inventory and plan recorded, Rocko checkpoint and Dewey author-boundary requests dispatched transport-only; no ACK/restart/recovery/publication claimed. Registry review deferred; C1/ACT-1 held.
- 2026-09-08 — darkwing for PUB-REC-ROCKO-1 — Rocko bounded inventory/checkpoint received; coordinator verified hashes and isolated unexecuted test, owns shared registration due three-artifact task limit. Checkpoint ready for Jason normal restart; recovery not yet tested; runtime identifiers excluded from publication pending curated evidence.
- 2026-09-08 | Filbert | PUB-REC-FILBERT-WUI-1 independent WUI draft-publication review | APPROVED at manifest a585c1eedb17044962c0419861a1032b23409b769c5d304aceff6ef6089a0e11 (53 files verified before/after); standalone deps closed, no network refs; font OFL provenance verified; author claims reproduced exactly on fresh isolated reruns (840/8220/240, 0 failures); two coordinator-judgment notes (F1 full name, F2 owner quote); visual pixel inspection bounded NOT RUN; verdict docs/plans/reviews/2026-09-08_publication-trial-wui-verdict.md; no source edits, git ops, or live-seat mutation.
- 2026-09-08 | Filbert | WUI verdict correction appended (terminal-log notice) | Publication-safety section had credited coordinator PNG inspection that actually occurred after the verdict; correction appended to docs/plans/reviews/2026-09-08_publication-trial-wui-verdict.md citing the disposition record; reviewer visual NOT RUN unchanged; no reply sent per sender instruction.
- 2026-09-08 — darkwing for PUB-REC-ROCKO-1 — worker recovery artifact received; recorded one reserved isolated test invocation, 1 pass/0 fail exit 0. Coordinator verified pinned test/launcher and pre/post-send artifact hashes; owner restart/neutral continue reports recorded. Raw runtime identifiers excluded from publication; curated summary and frozen evidence sent to Filbert for independent bounded recovery review. Trial acceptance remains pending.
- 2026-09-08 | Filbert | PUB-REC-FILBERT-RECOVERY-1 independent recovery-evidence review | Bounded planned-checkpoint recovery SUPPORTED; curated summary APPROVED for publication at 0e17757cfd3af3bfd3003957550d78c37d32c2b11c75c2b10c76fb9bb5a28a07; all ten snapshot hashes verified at manifest b52a6215, pre-send recovery prefix 52778f1a reproduced exactly, reserved-test isolation confirmed by source read without rerun; inference/procedural limits preserved; verdict docs/plans/reviews/2026-09-08_publication-trial-recovery-verdict.md; no execution, private reads, or git ops.
- 2026-09-08 — darkwing — PUB-REC-FILBERT-RECOVERY-1 independently SUPPORTS bounded planned-checkpoint recovery and APPROVES summary 0e17757c; conditions accepted, originals remain local. Inventory fixes: bounded Pi fixture copy (4 tests passed), TOOLS flags, inactive skill compatibility/provenance note. PUB-REC-FILBERT-LAUNCHER-1 sent to Filbert/default at manifest 8900faf1 for exact 23-candidate review; transport exit 0, application acceptance unknown. Return event: declared launcher verdict; follow-up owner Darkwing. No trial acceptance or publication yet.
- 2026-09-08 | Filbert | PUB-REC-FILBERT-LAUNCHER-1 final launcher candidate review | APPROVED for publication: 23 candidates at manifest 8900faf1 (57/57 hashes verified before/after); fixture reruns 4/4 and 1/1 pass in disposable copy; pinned rocko test/launcher and SKILL.md byte-identical to prior pins; host/container separation, refusals, session validation, docs consistency, and publication-safety scan all verified; two non-blocking notes (cosmetic duplicate assignment, argv observation left documented); verdict docs/plans/reviews/2026-09-08_publication-trial-launcher-verdict.md; no live launches, private reads, or git ops.
- 2026-09-08 — darkwing — Owner Sonnet launcher change reconciled with README and isolated test expectation; 1 pass/0 fail, no model call. PUB-REC-FILBERT-SONNET-1 focused review requested; historical recovery evidence unchanged, revised publication bytes require new approval.
- 2026-09-08 | Filbert | PUB-REC-FILBERT-SONNET-1 focused sonnet-delta review | REQUEST CHANGES: three-file delta itself correct/minimal (launch.sh, test, README all sonnet-consistent; isolated rerun 1/1 pass; recovery evidence untouched) but agents/rocko/CONTEXT.md in the same snapshot still says Fable at launch injection, and previously approved agents/README.md + agents/darkwing/SOUL.md carry stale Fable references; refreshed narrow delta converts to approval; verdict docs/plans/reviews/2026-09-08_publication-trial-sonnet-verdict.md; no live launches or private reads.
- 2026-09-08 — darkwing — SONNET-F1/F2 fixed after independent REQUEST CHANGES: three context/team model references now match Sonnet; combined isolated launcher tests 5/5 pass. PUB-REC-FILBERT-SONNET-2 frozen delta sent for re-review, transport exit 0 application acceptance unknown; required return is R2 verdict, follow-up Darkwing. Earlier rejected verdict and historical recovery bytes preserved.
- 2026-09-08 | Filbert | PUB-REC-FILBERT-SONNET-2 focused sonnet-delta round-2 review | APPROVED: three one-line Fable-to-Sonnet repairs verified minimal (rocko CONTEXT.md, agents/README.md, darkwing SOUL.md); no fable references remain in the seven-file snapshot at manifest c5ad6306; combined fixtures rerun independently 5/5 pass in disposable harness over approved dependencies; exactly six changed candidates vs original approval; R1 rejection preserved; verdict docs/plans/reviews/2026-09-08_publication-trial-sonnet-r2-verdict.md; no live launches or private reads.
- 2026-09-08 — darkwing — PUB-REC-FILBERT-SONNET-2 independently APPROVED six revised publication candidates at c5ad6306, combined reviewer fixtures 5/5 passed. Coordinator verified seven frozen/live file hashes, no drift. R1 rejection and historical recovery bytes preserved. Acknowledgement transport exit 0, application acceptance unknown; no reply requested. Final selective publication remains pending.
- 2026-09-08 — darkwing for Filbert — PUB-REC-FILBERT-FINAL-1 APPROVED 92 exact publication units at manifest 3f8e765b; final-verdict receipt preserved. Published at 29c1defe29e5793022e1d3820b265bfc0f7f628a, committed-tree fixtures 5/5 passed, push and fresh origin/refactor identity verified. Upstream OFL whitespace preserved; authored-path whitespace check passes, full check does not. Raw/unreviewed drift remains local. Jason trial acceptance pending; no deployment.
- 2026-09-08 — darkwing — Jason accepted bounded #1497 publication/recovery trial after plain-language recommendation: "THAT is an executive brief. Proceed." Acceptance comment 25943 recorded, issue closed. Source 29c1defe and closeout 10448e41 remain unchanged; no WUI design or production acceptance. CURRENT returns to deferred registry review alignment only.
- 2026-09-08 — darkwing — #1498 owner goal skill/launcher mismatch: isolated Pi launcher fixtures reproduced failure, stale required ms-agent-watch path absent while ms-watch replacement exists. Plan docs/plans/2026-09-08_skill-launcher-mismatch.md; no live launch or deployment. Other work preserved.
- 2026-09-08 — darkwing for Filbert — #1498 SKILL-LAUNCHER-FILBERT-1 independently APPROVED c4dd2ad8; exact repair published f3dce320, remote verified, committed-tree fixtures 5/5 passed. Rename-display assertion issue reconciled before push via expanded path/byte verification; completion receipt preserves it. No live activation or unrelated changes.
+182
View File
@@ -0,0 +1,182 @@
# TOOLS.md — command and tool reference
On-demand reference for agent sessions (conductors, bootstrapping agents,
reviewers). `AGENTS.md` routes here; this file carries the depth: usage,
inputs/outputs, exit codes, and safety notes for every entry point.
Reading guide: system entry points are `scripts/*.sh` (bash) or invoked via
`node scripts/mosaic-task.mjs` (node). Host-side helpers under `tools/`
(tmux messaging, watchers, prose checker) are covered under Tools
(host-side) below. Every script fails closed — missing
or invalid configuration/policy refuses the operation with a nonzero exit
and changes nothing.
## Lifecycle
| Command | Purpose | Notes |
|---|---|---|
| `scripts/bootstrap.sh` | Create `~/.config/mosaic-dev/config.json` if absent | Idempotent; existing config validated, never rewritten |
| `scripts/build.sh` | Build the release image | Tag derived from `RELEASE` + pinned pi version |
| `scripts/hello.sh` | One-shot startup request | Prints model response on stdout |
| `scripts/verify.sh` | Full gated test | Exit 0 only on exact `MOSAIC_HELLO_OK`; `EXPECTED_MARKER` overrides for negative drills |
## Tasks (missions, runs, evidence)
| Command | Purpose | Notes |
|---|---|---|
| `scripts/run-task.sh run <task.json>` | Execute a task | Immutable run record under `<dataRoot>/runs/` |
| `scripts/run-task.sh validate <task.json>` | Strict validation | Writes nothing |
| `node scripts/mosaic-task.mjs show <runId>` | Inspect a run | Full record + snapshots + artifacts |
| `node scripts/mosaic-task.mjs list` | List runs | task/workspace/session columns |
| `node scripts/mosaic-task.mjs retry <runId>` | Re-execute a run's snapshot | New run dir; `retriedFrom` lineage recorded |
| `node scripts/mosaic-task.mjs prune [--keep=N] [--yes]` | Retention | Dry-run default; receipt in `runs/.pruned.log` |
| `node scripts/mosaic-task.mjs resolve-role <roleFile>` | Validate a role contract | Prints `MOSAIC_ROLE_TOOLS` / `MOSAIC_ROLE_NETWORK`; config-free |
Task fields: `prompt` (required), `mission` (path), `expectExact`,
`timeoutSeconds` (5600), `workspace` (`:run` or named), `capabilities.tools`
(allowlist: read write edit bash grep find ls), `session`,
`sessionForkFrom` (requires `session`). Mission fields: `objective`,
`directives[]`, optional governing `capabilities.tools`. Policy: a task may
narrow a mission's tools, never widen; empty intersection = tool-free run.
## Agent (interactive TUI)
```bash
scripts/agent.sh <name> [--mission <file>] [--workspace <ws>] [--session <s>] [--tools <list>]
```
Launches an interactive pi TUI inside the container with the four immutable
contracts + optional mission + agent identity as its system prompt,
persistent named session, optional workspace. Exit with `/quit`.
A seat role (`agent.json` `role`) binds to `roles/<role>.json` (M18): the
contract's tools are a ceiling the seat definition or `--tools` may narrow,
never escalate past. Missing/invalid contract refuses the launch; empty
intersection = loud tool-free seat. An explicit `MOSAIC_AGENTS_DIR` override
that cannot resolve the named seat also refuses (#46) — unset the override
for the M13 plain governed TUI. `--auth <account>` injects
`auth.<account>.json` (beside the active credential file) as the launch's
`PI_AUTH_FILE`; a missing/invalid account refuses (M19).
For native repository development, opt in with a **leading** `--host-dev`:
```bash
scripts/agent.sh --host-dev darkwing [--fresh] [--check] [--soul FILE] [--constitution FILE] [--user FILE] [--provider NAME] [--model ID] [--thinking LEVEL]
```
This mode delegates to `scripts/agent-host-dev.sh`, uses host Pi and repository
tools/skills plus the development goal extension, and keeps its own sessions
under `.pi/state/<name>/`. It uses native Pi authentication and does not run
container release alignment or apply managed seat role ceilings. It is a host
development session, not a sandboxed worker. Container-only flags such as
`--auth`, `--mission`, and `--tools` are rejected in this mode. Omitting
`--host-dev` retains the existing container lifecycle and policy checks;
container failures never trigger a host fallback. Darkwing's agent-local shim
selects host development explicitly. See `agents/darkwing/README.md`.
## Auth (credentials)
Credential checkpoint over pi's auth model (one `auth.json` keyed by
provider; resolution order `--api-key``auth.json` → env → models.json).
No credential material is ever printed — provider names, credential types,
and env var NAMES only.
Ownership rule (#48): `~/.pi` is read-only to the stack, permanently. The
only interaction is the existing read-only container mount of the default
credential (`PI_AUTH_FILE`, default `~/.pi/agent/auth.json`). Mosaic-managed
accounts live under the data root: `<dataRoot>/auth/<account>.json`, perms
0600 (mirroring `scripts/gitea-api.sh` hygiene — loose perms are flagged in
listings and refused by `--auth`).
| Command | Purpose | Notes |
|---|---|---|
| `scripts/auth.sh status` | Report both credential sources | Default harness credential (read-only) + mosaic-managed accounts; never prints material |
| `scripts/auth.sh accounts` | List mosaic-managed accounts | Under the data root; marks the active one; flags non-0600 |
`agent.sh --auth <account>` injects `<dataRoot>/auth/<account>.json` as the
launch's `PI_AUTH_FILE`; missing/symlinked/non-0600 accounts refuse.
Headless task runs keep the default credential.
## Release
| Command | Purpose | Notes |
|---|---|---|
| `scripts/release.sh package` | Build + tag the release image | Tag: `mosaic-poc-agent:<pi>-r<release>` |
| `scripts/release.sh activate` | Health gate → atomic pointer swap | `--fault-injection` proves the refusal path |
| `scripts/release.sh rollback` | Health-gated return to previous | Refuses if image missing |
| `scripts/release.sh status` | Release, tag, active pointer, log | Safe on empty state |
| `scripts/release.sh ensure` | Self-determination: align active pointer to `RELEASE` | Fast path restores a missing/mismatched pointer without a gate; slow path packages + health-gates first. Invoked automatically at launch |
## Conductor (worker patches)
```bash
scripts/conductor-apply.sh <runId> [--dry-run]
```
Auto-applies a worker's patch under `roles/conductor-policy.json`:
succeeded run → clean target tree → path allowlist → syntax gates →
apply → policy suites → attribution commit. Any failure reverts.
Push is never automatic.
## Maintenance
| Command | Purpose | Notes |
|---|---|---|
| `scripts/reset.sh` | Delete the data root | Triple-safety-checked (path, symlink, ownership marker) |
| `scripts/test-config.sh` | Config selftests (no Docker) | 24 cases |
| `scripts/test-task.sh` | Task selftests + live cases | 90 cases |
| `scripts/test-release.sh` | Release selftests | 14 cases |
| `scripts/test-conductor.sh` | Auto-apply selftests (sandboxed) | 17 cases |
| `scripts/test-auth.sh` | Auth checkpoint selftests (no Docker) | 13 cases |
| `scripts/gitea-api.sh <METHOD> <path> [body]` | Gitea API helper | Token never on argv/stdout |
## Tools (host-side)
Host-side helpers under `tools/`, outside the `scripts/` command surface.
Per-tool READMEs: `tools/tmux/README.md` and `tools/unslop-hook/README.md`.
| Command | Purpose | Notes |
|---|---|---|
| `tools/tmux/agent-send.sh` | Inter-agent tmux message with addressing preamble | Reliable submit (bracketed paste, Enter flush, draft detection); ships `send-message.sh` over ssh for remote panes (remote needs only bash + tmux + base64) |
| `tools/agent-watch/agent-watch.sh` | Condition watcher per agent seat | One transient systemd `--user` timer + service per watch; fires `agent-send.sh` when the condition command exits 0 |
| `node tools/unslop-hook/unslop-check.js <file>` | Mechanical AI-tell prose check | Dependency-free node CLI + module driven by `lists.json`; `extension.ts` is the pi extension wrapper |
`agent-send.sh` prepends the preamble
`[<src_host>:<src_session> -> <dst_host>:<dst_session>]`; `-C`/`--class` adds
a ` class=<CLASS>` token (`terminal-log`, `actionable`, `human`, `reaction`,
`digest`; consumers treat an absent class as `actionable`). Flags: `-s` dst
session (required) · `-H` ssh target for a remote pane · `-L` named tmux
socket · `-n` dst hostname for the preamble · `-m`/`-f`/stdin message body ·
`-S` source-label override · `-r N` Enter-flush attempts (default 2) · `-v`
verbose · `-h` help. Exit codes: `0` delivered/queued · `1` target not found ·
`2` still draft · `3` usage error · `4` ambiguous socket (the session exists
on more than one tmux server; disambiguate with `-L` or `MOSAIC_TMUX_SOCKET`).
`agent-watch.sh` subcommands: `start --name <id> --session <session> --when
'<shell command; exit 0 = met>' --message <text>` with `--class`,
`--interval` (default 30), `--timeout` (default 3600), `--repeat`,
`--quiet-timeout`, `--socket` · `list` · `status [--json]` · `stop <name>` ·
`log <name>` · `meta-install [--interval 300] [--unit-name <unit>]` ·
`meta-remove [--unit-name <unit>]`. Interval floor is 10s (a watcher is a
fallback cadence, never a tight poll); hidden `_tick`/`_scan` subcommands run
inside the systemd services. `status` exit codes: `0` clean · `3` any stale
watch or dead meta-watch · `6` systemd user bus unreachable. Delivery goes
through `agent-send.sh`; rc `2` means the text reached the pane as an
unsubmitted draft, which counts as delivered and is not retried (other
failures retry twice, then the watch gives up). Watches are one-shot by
default; `--repeat` re-arms. Notices carry a `[watch:<name>]` prefix.
`unslop-check.js` checks a file (or stdin) against the word, phrase,
punctuation-density, and pattern lists in `lists.json`, stripping fenced and
inline code first so a quoted mention never flags. Invocation:
`node tools/unslop-hook/unslop-check.js <file>`; `UNSLOP_LISTS=<path>`
overrides the lists location. Exit codes: `0` clean · `1` violations (findings
printed as JSON on stdout) · `2` gate broken (invalid lists or unreadable
input; error on stderr, never a clean verdict).
## Exit-code convention
`0` success · `1` operation failed · `2` invalid data/configuration ·
`3` configuration missing for a read operation · `4` usage/file/environment
problem. Scripts print diagnostics on stderr; model responses (and only
model responses) on stdout.
+31
View File
@@ -0,0 +1,31 @@
# Mosaic Stack concepts
These pages explain Mosaic's own concepts and design direction. Each states its
implementation status. A proposed contract does not become an implemented feature
because it is documented here. Current demo compatibility and ACT-1's migration
gates remain in force.
| Concept | What it explains |
|---|---|
| [Agent personality](soul.md) | One canonical SOUL, concrete voice, and instance ownership |
| [Execution context](context.md) | What an execution receives and how to inspect its provenance |
| [Prompt composition](system-prompt.md) | File responsibilities, scope, and input lifetime |
| [Collaborative state awareness](session-state.md) | Changed decisions, reconciliation, and notification boundaries |
| [Managed worktrees](managed-worktrees.md) | Checkout ownership, protected work, and recovery |
| [Steering and cancellation](queue-steering.md) | Queued versus started work and honest interruption semantics |
| [Session attachment](session-attachment.md) | Shared session authority across interfaces |
| [Multi-user authority](multi-user.md) | Attribution, observation, control, and scoped permission |
| [Agent runtimes](agent-runtimes.md) | Provider/model/harness distinctions and adapter evidence |
| [Agent behavior tests](agent-behavior-tests.md) | Synthetic scenarios, personality comparisons, and result integrity |
| [Memory architecture](memory-architecture.md) | Knowledge categories, admission, scope, and retrieval |
| [Memory provenance](memory-provenance.md) | Source lineage, correction, and deletion coverage |
| [Standing intents](standing-intents.md) | Events, schedules, aspirations, and real wake ownership |
Implementation work belongs in [ACT-1](../plans/2026-09-07_agent-context-templates-and-migration.md)
and related foundation plans. Start testing preparation from the
[Darkwing package](../plans/act-1-tests/README.md).
This directory is the home for conceptual explanations. `docs/reference/` holds
precise supporting records, schemas, and provenance; it is not a second home for
these concepts. [Source attribution](../reference/concepts/README.md) preserves
the origin and license of material adapted into this set.
+39
View File
@@ -0,0 +1,39 @@
# Agent behavior tests
Status: ACT-1's preparation package exists; model trials remain NOT_RUN unless
an execution record establishes otherwise.
Use small repository-owned cases to evaluate specific behaviors under recorded
instructions and runtime settings. A test should name what it proves and what it
does not. Avoid a second runner when an existing harness can execute the case.
## Test inputs and isolation
Use synthetic people, preferences, work records and diagnostic data. Give every
trial an explicit isolated workspace/session binding. Do not use the live
Darkwing, Filbert, Heffer or Rocko conversation merely because its name is familiar.
A personality comparison injects exactly one SOUL per trial. Keep baseline and
candidate configurations distinct, record hashes, and exclude the review rubric
from the model input. Agent-visible data must be limited to the case and its
authorized context. Prompt instructions alone do not enforce filesystem isolation.
## Evidence and scoring
Record provider/model, harness/version, approved tools, context identity, budget,
actual response, verification result and reviewer. Preserve failed and ambiguous
attempts. Use NOT_RUN, PASS, FAIL, BLOCKED and DEFERRED accurately.
Mechanical tests can verify wiring and refusal behavior. Model trials can assess
reasoning and style. Neither can substitute for the other's evidence. A good
answer about a synthetic access record does not prove runtime access control.
Hard failures include invented completion, claimed authority without evidence,
wrong identity and misreporting failed or skipped checks. Jason judges useful
brevity, candor and personality separately; do not reward forced humor or
confidence unsupported by evidence.
The current [ACT-1 pack](../plans/act-1-tests/README.md) has eleven synthetic cases
and a preparation utility. It also reuses existing launcher regressions. Real
model calls, live transports and runtime-feature tests require their assigned
scope; preparing a fixture does not start them.
+45
View File
@@ -0,0 +1,45 @@
# Agent runtimes and adapter ownership
Status: Pi is the reference harness; additional harness support must be established
through pinned adapter contracts and tests.
| Layer | Meaning |
|---|---|
| Provider | Model service and its authentication/transport |
| Model | Selected model and supported settings |
| Harness/runtime | Program that executes the model/tool loop |
| Deployment | Host development or managed container execution |
| Interface/transport | Where a user or authorized service interacts with the execution |
Changing a provider is not the same operation as changing the harness or deployment.
## Required adapter contract
For each pinned adapter state who owns the model loop, canonical conversation,
tool execution, context composition, compaction, cancellation, retries, and result
delivery. Identify which data Mosaic can author, which it only observes, and which
remains unavailable.
Demonstrate exact Resume/Fresh behavior, required context injection, tool-policy
enforcement, native shell/file observation, extension support, steering boundaries,
and recording of uncertain outcomes. Mark unsupported and untested behavior
explicitly. A successful startup is only startup evidence.
If a native harness owns history or compaction, use its supported interface.
Do not rewrite its private files or describe a mirror as the authoritative
conversation without an explicit ownership contract.
## Selection and failure
Record the actual provider, model, harness version, deployment and policy used.
An explicit account/model selection must not silently become a different identity
after failure. Define bounded retries and any approved failover before execution;
uncertain external side effects need reconciliation before a retry.
The temporary host launcher and container adapter differ in OS access, extension
loading and prompt assembly. Neither name nor tool allowlist alone proves equal
isolation. Preserve those distinctions in diagnostics and tests.
ACT-C07 tests interpretation of a capability matrix. It does not certify an
adapter. See [prompt composition](system-prompt.md),
[steering](queue-steering.md), and [adapter contract](../../adapters/README.md).
+41
View File
@@ -0,0 +1,41 @@
# Execution context
Status: target design with a partial native-development implementation.
[ACT-1](../plans/2026-09-07_agent-context-templates-and-migration.md) governs rollout.
Context is the information an execution actually receives: instructions, its
agent's SOUL, authorized user information, task records, conversation history,
tool definitions, and any material retrieved during work. A file's presence in
the repository does not mean it was injected.
## Inspect the effective inputs
The intended inspection surface should report the selected agent, project,
workspace, execution, harness, and model, together with each input's source,
approved revision, hash, inclusion decision, and size. Report exclusions and
their reasons. Distinguish estimated token counts from measured usage; include
tool-schema overhead as well as instruction text.
Exactly one agent-owned SOUL is eligible. Root and shared-default SOULs are not
fallbacks in the target design. Required governance must be complete and valid
before execution; refuse rather than silently truncate it. Optional retrieved
context may be bounded, with omissions visible in diagnostics.
Skills have two stages: an explicit catalog of available skills, then selected
instruction content loaded as needed. Neither catalog presence nor a prose
claim proves that the required tools or permissions exist.
## Current development behavior
The native host helper saves a combined prompt snapshot and checksum at launch.
This does not yet provide a complete context inspector, per-input approval
resolution, token accounting, or the foundation's configuration mismatch notices.
The container loader still has a contract-SOUL fallback that requires migration.
Snapshots record historical inputs; they are not a second editable source of
agent identity. Current approved inputs are resolved at each Resume or Fresh
launch. An already-running execution must not silently reload edited files.
See [prompt composition](system-prompt.md), [SOUL](soul.md), and
[behavior tests](agent-behavior-tests.md). ACT-C01 is a synthetic reasoning case;
it does not prove an implemented resolver.
+42
View File
@@ -0,0 +1,42 @@
# Managed development worktrees
Status: proposed development lifecycle; no new allocator or cleanup service exists
as a result of this documentation.
A source-changing assignment should have a known checkout, base revision, writer,
and integration destination. Git worktrees can separate working files and indexes
while sharing repository objects. They are not filesystem or credential sandboxes.
## Ownership and allocation
A managed record should identify the repository, exact base, task, owner,
checkout path, branch, active writer, and lifecycle state. A named checkout is not
proof of a valid assignment. Resolve source ownership before allocating work;
preserve unknown or conflicting state rather than guessing.
Check capacity before allocation and setup. Failure must leave clear evidence
and recoverable state. Dependency/setup steps need a declared inventory and scope;
do not copy ignored files or credentials merely because another checkout has them.
Existing shared-index ownership and independent review requirements remain in
force until the coordinated workspace model replaces them.
## Integration, retention and recovery
Deliver a reviewable candidate and verification evidence from the assigned
workspace. The authorized integrator applies it to the intended destination.
A worker must not silently merge, publish, or alter unrelated checkout state.
Closing work retires it from ordinary use and preserves evidence. It does not
authorize deletion. Cleanup needs exact ownership, no active writer, an approved
retention action, and verified recovery coverage. Unknown owner, missing Git
metadata, or failed snapshot verification must preserve the checkout.
Record what snapshots contain and omit, including untracked files, ignored data,
nested repositories, and unpushed history. Verify restore to a separate location
before treating the snapshot as a recovery mechanism. Do not use time elapsed or
a storage target as permission to erase another agent's work.
ACT-C03 is a synthetic cleanup recommendation test. Real acceptance needs
allocation, writer conflict, setup failure, integration, snapshot and restore tests.
See [ACT-1](../plans/2026-09-07_agent-context-templates-and-migration.md).
+45
View File
@@ -0,0 +1,45 @@
# Memory architecture
Status: design direction for later adaptation; this document does not introduce
a memory service or change deployed user files.
Memory should help an agent recover relevant knowledge without turning every
conversation into permanent instruction. Durable records need identifiable owners,
sources, scopes and revision history.
| Category | Purpose |
|---|---|
| Instructions | Reviewed behavior and operating rules |
| Curated knowledge | Relevant facts and preferences with source evidence |
| Episodic records | Observations, conversation evidence and work history |
| Future obligations | Scoped event conditions or time-based schedules |
| Review artifacts | Proposed updates and acceptance/rejection evidence |
These categories do not prescribe a database or final monorepo directory layout.
## Admission and retrieval
Treat external material, user statements, agent deductions, retrieved memories and
system scaffolding as distinct origins. Repetition or retrieval must not upgrade
trust. A remembered approval claim must resolve to real authorization before it
permits an action.
Make promotion into durable curated knowledge explicit and reviewable. Preserve
source scope, time, supersession and uncertainty. Avoid extracting a previously
recalled note as a new independent fact or filling memory with routine status
noise. Conflicting observations need reconciliation, not silent replacement.
Retrieve within the current user's/project's/workspace's permissions. Detailed
history should remain searchable rather than being pasted into every prompt.
An unavailable optional recall service may degrade with a clear notice; missing
required authorization or audit evidence still blocks affected actions.
## Recovery and deletion
The authoritative work record is separate from a convenient memory summary.
Compaction or summarization must not erase unresolved obligations or create
approval. Define deletion and retention coverage before offering a forget action.
See [memory provenance](memory-provenance.md), [standing intents](standing-intents.md)
and foundation R28. ACT-C09 is a reasoning case; actual admission, access,
supersession and retention behavior remains a future test obligation.
+41
View File
@@ -0,0 +1,41 @@
# Memory provenance, correction and deletion
Status: proposed contract for a future memory subsystem.
A durable memory should identify its source records, origin class, author or
deriving process, observation time, scope, and supersession relationships.
Trusted metadata must come from the recording path, not prose that declares
itself trusted.
## Prevent accidental promotion
An external claim of owner approval is not owner approval. Agent deductions must
retain their derivation and uncertainty. Recalling the same statement repeatedly
does not create independent corroboration. Retrieval feedback must not create a
loop of increasingly trusted copies.
Treat unknown lineage as unknown. Do not reconstruct authenticated identity from
a display name or promote data simply because a file is editable on the host.
Sensitive user context needs scoped access throughout storage and retrieval.
## Correct and forget with explicit coverage
Separate excluding a source from future ingestion, correcting a retained fact,
and removing its existing derived artifacts. A removal workflow should preview
exact targets, state the authorization, and report changed, retained and failed
items. Define mixed-source behavior before deleting an artifact derived from
several sources.
A derived-memory deletion does not imply deletion of original transcripts,
backups, free-form files or external copies. Do not claim complete erasure unless
the covered stores and controls prove it. Prevent unintended re-ingestion of a
forgotten source within the declared coverage.
Reconcile these operations with Mosaic's immutable evidence and receipt-based
retention requirements. Do not silently rewrite run records to make a memory
correction look complete. Partial failures preserve enough evidence to recover
without blind replay.
ACT-C09 tests source skepticism and deletion-limit reasoning. Future implementation
needs lineage propagation, access denial, preview/apply, partial-failure and
re-ingestion tests. See [memory architecture](memory-architecture.md).

Some files were not shown because too many files have changed in this diff Show More