Publish reviewed development agents and WUI draft with recovery evidence (#1497)
@@ -1827,6 +1827,50 @@ notices: Rocko delivered; Filbert and Dewey delivery unconfirmed (input boxes no
|
||||
locatable), no retries. Root README/AGENTS/CURRENT and compatibility symlink carry
|
||||
the new identity regardless of transport. No claim of their acknowledgement.
|
||||
|
||||
|
||||
## 2026-09-08 — Owner-requested development team launchers
|
||||
|
||||
Before: Darkwing and the newly added Dewey used the shared native Pi launcher;
|
||||
Rocko and Filbert had no project-local launchers. Darkwing's persona did not
|
||||
explicitly identify the development team lead.
|
||||
|
||||
After: Rocko launches Claude Code with the installed Fable model alias and a
|
||||
recorded per-agent UUID for exact resume. Filbert launches pinned Pi with
|
||||
openai-codex/gpt-6-astra and explicit low thinking. The shared Pi helper accepts
|
||||
per-launch model/provider/thinking inputs. Darkwing leads the team; Dewey owns
|
||||
frontend/UX; Rocko and Filbert support general project assignments. Local
|
||||
personas, context, usage documentation and a team directory describe the roles.
|
||||
|
||||
Verification: five offline tests pass across all four launchers and the default
|
||||
container entry point, including context, model selection, fresh/resume and
|
||||
refusals. Rocko and Filbert real --check commands pass; the local Pi offline
|
||||
catalog lists the requested model. Shell syntax and git diff whitespace checks
|
||||
pass. No live authenticated/model conversation was tested, no fleet registration
|
||||
or role authority changed, and no commit or push was made.
|
||||
|
||||
## 2026-09-07 — Authorized commit/push wave, transport-only review checkpoint
|
||||
|
||||
Before: A9 pending in CURRENT; pending foundation/launcher/docs/skills/log work uncommitted; tmux confirmation unreliable. Owner accepted A9 and authorized grouped commits, full suites, refactor plus 17 tags, and #53 inclusion evidence for owner closure. Five grouped commits landed locally. Task/release passed 90/0 and 14/0; initial failures remain recorded in the new A9 note.
|
||||
|
||||
Corrections: em-dash/redraw root-cause claims were unsupported. C-locale parser defect was reproduced, but later independent R3 review demonstrated six false confirmations with retained hidden drafts. First review also failed because the candidate changed during admission; later exports were frozen. No claim of reliable application delivery survives those findings.
|
||||
|
||||
Owner selected transport-only semantics: checked load/paste/one Enter, application acceptance unknown. R4 transport tests pass five cases, wrapper 19/0, private named-socket and C1-C6 scratch contract controls pass. Immutable R4 export/request and explicit transport-only receipt are under docs/plans/reviews. Final independent approval remains pending; no push/deployment/issue closure. A9 accepted separately; #53 local planning acceptance mapping prepared; final remote inclusion pending. Registry review is authorized next after this wave, not implementation.
|
||||
|
||||
|
||||
## 2026-09-08 — Dewey WUI brand board, local review package
|
||||
|
||||
Late-recorded phase entry: before implementation, owner requirements and approval boundaries were captured in agents/dewey/work/wui/BRIEF.md, DECISIONS.md and TASKS.md; no separate BUILD-LOG start entry was written. Before: no WUI brand artifact. After: index.html provides three original logo studies, three locally bundled sans-serif families, consistent outline icons, ten theory-backed palettes and Light/Dim/Dark modes, with review-note/token downloads and labeled component specimens.
|
||||
|
||||
Author verification: Chromium 152 via local CDP checks; 840 token pairs, 8,220 rendered-text samples, 240 responsive combinations from 320 to 3440 px, breakpoint/keyboard/target/download/fallback checks, and screenshot inspection. Mobile icon-label clipping and doubled-text overflow were fixed and rechecked. VERIFY.md records exact limits and test-driver corrections. Public t3.codes/buzz.xyz inspection is recorded separately; no v1 inspection. This is a standalone design-review package, not a product delivery. No issue lifecycle or independent technical acceptance was performed. Jason's branding decision remains pending; no dashboard/backend work, integration, deployment, commit, or push by Dewey.
|
||||
|
||||
## Commit/push wave completed — R5 transport contract
|
||||
|
||||
Filbert independently APPROVED frozen R5; working/source hashes matched. Approved correction and evidence committed as 69f10a40 (#1496), then refactor plus exactly 17 tags pushed atomically and all 18 remote refs verified. Six #53 planning artifacts verified in published commit; owner closure evidence at docs/plans/reviews/2026-09-07_issue53-closeout.md. A9 acceptance recorded; config/auth/conductor/foundation/extension/task/release 24/15/17/43/18/90/14 all green. Transport and remote-shell injection controls passed; live transport reported acceptance unknown as required. Registry review alignment is next. No trunk merge/deployment; newer relocation changes preserved unstaged.
|
||||
|
||||
## 2026-09-08 — #1497 publication/recovery trial start
|
||||
|
||||
Before: remaining launchers/agent definitions, WUI drafts, skill and shared records were pending after the prior publication wave. Jason approved temporary agent-definition publication, draft labels, current-terminal end-to-end assignment, independent review, one planned operator restart and trial-only refactor push after tests. Plan and bounded requests under docs/plans/2026-09-08_publication-recovery-trial.md. Initial inventory found 94 untracked candidate paths, not yet publication-safety certified. Rocko requested to prepare a durable checkpoint with one unexecuted verification action; Dewey requested to declare authored draft boundaries and active writes. Transport dispatch is not ACK. No source adoption, restart, model call, commit/push or deployment in this kickoff. Registry review deferred by the newer owner priority.
|
||||
|
||||
## 2026-09-08 — #1497 recovery evidence and source-review candidate
|
||||
|
||||
Rocko reports one reserved post-restart isolated test invocation, 1 pass/0 fail exit 0 after operator restart/neutral continue. Filbert independently SUPPORTS bounded recovery and APPROVES curated summary 0e17757c with raw records withheld; exact resume mode inferred and execution count worker-reported, not runtime guarantees. Independent ten-file snapshot manifest b52a6215. Coordinator corrected Pi fixture recursive-copy coupling (four tests passed), TOOLS flag gap and added inactive-skill compatibility/provenance note; original Rocko test/launcher pins unchanged. Final 23-candidate launcher/source snapshot manifest 8900faf1 submitted for independent review. No commit/push or owner trial acceptance yet.
|
||||
|
||||
@@ -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.
|
||||
@@ -1,7 +1,7 @@
|
||||
# SOUL — Darkwing
|
||||
|
||||
You are Darkwing, Mosaic Stack's hands-on engineering collaborator. Your job
|
||||
is to help Jason make the system dependable by using it, finding where it
|
||||
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
|
||||
@@ -18,3 +18,12 @@ 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.
|
||||
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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 "$@"
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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
|
||||
@@ -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 |
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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.');
|
||||
})();
|
||||
@@ -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);
|
||||
@@ -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.');
|
||||
@@ -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})));
|
||||
@@ -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;
|
||||
|
After Width: | Height: | Size: 136 KiB |
|
After Width: | Height: | Size: 136 KiB |
|
After Width: | Height: | Size: 135 KiB |
|
After Width: | Height: | Size: 150 KiB |
|
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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 53 KiB |
|
After Width: | Height: | Size: 155 KiB |
|
After Width: | Height: | Size: 157 KiB |
|
After Width: | Height: | Size: 200 KiB |
@@ -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>
|
||||
@@ -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}}
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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[@]}"
|
||||
@@ -107,4 +107,35 @@ are never rewritten or removed; corrections are new entries.
|
||||
| 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.
|
||||
|
||||
@@ -61,7 +61,7 @@ for the M13 plain governed TUI. `--auth <account>` injects
|
||||
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]
|
||||
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
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
# Publication and planned-restart trial
|
||||
|
||||
Owner: Jason. Coordinator: Darkwing. Authorized by Jason's final `agreed` after ms-grill-me rounds 1–4. Baseline HEAD: 3b7fd19d087226b1887bf017fc10ef16b044f6aa, branch refactor, canonical checkout /mnt/storage/src/mosaic-stack.
|
||||
|
||||
## Outcome
|
||||
|
||||
Publish the remaining reviewed repository changes and prove a useful development assignment survives one planned participating-agent restart without Jason reconstructing its briefing. The operator performs the restart only after checkpoint readiness is established. This is a planned-checkpoint test, not crash recovery or production orchestration certification.
|
||||
|
||||
## Scope and owner decisions
|
||||
|
||||
Publish reviewed source, tests, skills, records, agent definitions/launchers and useful design drafts. Exclude credentials, private transcripts, runtime/session state, dependencies and generated caches. Inspect evidence/screenshots for publication safety and license provenance; do not decide from filename alone. Agent relocation to ~/.mosaic-dev is deferred. Existing tracked agents are not removed. C1 and ACT-1 remain held. Registry alignment is deferred behind this owner-prioritized trial, not automatically resumed.
|
||||
|
||||
Design drafts may be published with explicit pending-owner-acceptance labels. Publication does not approve WUI branding or authorize implementation/deployment. No force push, next/main merge, agent relocation, live config change or runtime authority expansion. Commit/push authorization is this trial's reviewed refactor changes only.
|
||||
|
||||
## Roles and stages
|
||||
|
||||
1. Darkwing inventories candidate paths and captures an exact review manifest; original authors retain ownership of their active files.
|
||||
2. Rocko is requested for bounded publication inventory/checkpoint work, separate from HELD Archify C1. No source ownership transfer. He reports any conflict rather than absorbing another active assignment.
|
||||
3. Dewey is requested to identify his publishable WUI draft boundary, original/license sources, test limits and active writes. Do not freeze or adopt his work without reconciliation.
|
||||
4. Filbert independently reviews the exact frozen publication candidate and recovery evidence. He must report any authorship/conflict; no self-approval.
|
||||
5. Rocko writes a durable checkpoint covering assignment/authority, decisions, evidence, incomplete work, unknown external outcomes and exact next action. He stops before that next action. Darkwing checks it without injecting an alternate briefing. Jason restarts Rocko when told ready.
|
||||
6. After normal resume, Rocko recovers the records without a reconstructed task prompt, states the checkpoint and performs the declared next bounded action once. Verify with artifacts and command/result evidence, not self-reported recall alone. If normal resume fails, record that failure before any assisted recovery; do not manufacture a pass.
|
||||
7. Applicable source and isolated launcher suites, publication-safety review and independent candidate approval precede selective commits and push. Verify fresh origin/refactor identity. Present end-to-end evidence to Jason for acceptance.
|
||||
|
||||
## Gates and current state
|
||||
|
||||
- Authorized plan: confirmed.
|
||||
- Initial inventory: 94 untracked candidate paths under agents/scripts/skills plus modified launchers/persona/shared records. Counts are a snapshot, not a safety verdict.
|
||||
- Worker assignment and author boundary: complete. WUI exact 53-file draft independently approved at a585c1ee, pending owner design acceptance.
|
||||
- Planned checkpoint recovery: independently SUPPORTED; curated summary 0e17757c APPROVED. Operator-reported restart, inferred resume mode and worker-reported execution count remain qualified. Raw runtime records stay local.
|
||||
- Source approval: 23 original candidates at 8900faf1, with six Sonnet revisions superseded by approved c5ad6306. Independent isolated tests 5/5 passed.
|
||||
- Final publication inventory and candidate-tree verification: in progress. Since approval, the executive-update skill changed, the tracked ms-agent-watch skill was deleted locally, and additional untracked skills appeared. These newer changes have no trial review or ownership handoff; preserve and exclude them, including the executive-update compatibility note. Do not restore deleted files or silently publish stale skill bytes.
|
||||
- Publication / remote verification / owner trial acceptance: pending. No live launches or unrelated skill migration is authorized.
|
||||
|
||||
No new /goal lifecycle is claimed by this document. Use this task plan and artifacts for tracking; an operator-set goal extension remains sole lifecycle owner.
|
||||
@@ -7,9 +7,33 @@ update this file to the next action). No ambiguity, no re-planning.
|
||||
|
||||
## Next action
|
||||
|
||||
Review `docs/plans/2026-09-03_auth-provider-harness-registry.md` and reconcile
|
||||
Gate 7 with later owner decisions and #53's workspace/session model. This is
|
||||
registry review alignment only; no registry implementation is authorized.
|
||||
Execute Jason's approved publication and planned-restart recovery trial (#1497).
|
||||
Plan: `docs/plans/2026-09-08_publication-recovery-trial.md`. Publish remaining
|
||||
reviewed changes, temporarily including agent definitions and labeled drafts;
|
||||
exclude private runtime/session/auth state. Jason performed Rocko's planned restart
|
||||
and issued neutral continue; PUB-REC-ROCKO-1 returned its reserved test PASS.
|
||||
Filbert independently SUPPORTS bounded checkpoint recovery and APPROVES the pinned
|
||||
privacy-safe summary (0e17757c); raw records stay local. No reliability or overall
|
||||
trial acceptance inferred. WUI exact 53-file draft publication is independently
|
||||
APPROVED with pending-acceptance label; source/default revisions remain unimplemented.
|
||||
PUB-REC-FILBERT-LAUNCHER-1 APPROVED 23 source/publication candidates at
|
||||
frozen manifest 8900faf1. Jason then changed Rocko's launcher to Sonnet.
|
||||
PUB-REC-FILBERT-SONNET-2 APPROVED the six revised candidates at c5ad6306;
|
||||
coordinator verified all seven R2 snapshot/live files unchanged. Remaining original
|
||||
candidate approvals stand. Independent combined fixtures passed 5/5. Preserve
|
||||
R1 REQUEST CHANGES and the historical Fable recovery evidence unchanged.
|
||||
Next gate: final tests and exact selective publication inventory with private raw
|
||||
records excluded, then commit/push refactor and request Jason's trial acceptance.
|
||||
Newer executive-update skill edits, local ms-agent-watch deletion and additional
|
||||
untracked skills are outside the pinned trial candidate. Preserve them uncommitted;
|
||||
exclude both executive-update files rather than publish unreviewed or stale bytes.
|
||||
Verify the prospective publication tree separately; live native launch would refuse
|
||||
because its required ms-agent-watch file is now locally absent. No live launch or
|
||||
unrelated skill migration is part of this trial.
|
||||
No further restart or re-briefing requested. C1 remains HELD.
|
||||
|
||||
Registry review alignment is deferred behind this newly prioritized owner trial.
|
||||
No registry implementation, agent relocation, main/next merge or deployment authorized.
|
||||
|
||||
Completed commit/push wave: R5 transport-only tmux correction independently
|
||||
APPROVED by Filbert, published on refactor at
|
||||
@@ -141,6 +165,10 @@ and unfinished-fixture status.
|
||||
|
||||
## Completed log
|
||||
|
||||
- 2026-09-08 — Owner-requested development team: Rocko launches Claude Code with Fable; Filbert launches Pi with `openai-codex/gpt-6-astra:low`; Darkwing is the development team lead and Dewey remains frontend/UX owner. Five offline launcher tests and both new agents’ local configuration checks pass. No model session started; inspector acceptance queue unchanged.
|
||||
|
||||
- 2026-09-08 — Owner-requested Dewey frontend/UX agent: `agents/dewey/launch.sh` uses the shared native launcher with its own persona, context and session history. Offline launcher checks pass for both agents and real Dewey `--check` passes; no model session started. Current inspector acceptance queue unchanged.
|
||||
|
||||
- 2026-09-07 — Owner-directed concept annexation: [Mosaic concepts](../concepts/README.md) now owns the adapted pages; source/license metadata moved to docs/reference/concepts. Test-package links and content hashes updated; preparation checks pass. Documentation ownership changed, not runtime behavior or the demo queue.
|
||||
|
||||
- 2026-09-07 — Owner-requested ACT-04 groundwork: [Darkwing concept test package](act-1-tests/README.md) prepared with twelve pinned OpenClaw references, synthetic cases, candidate SOUL and offline preparation utility. Import checks and existing isolated launcher tests passed; behavioral cases NOT_RUN and runtime features deferred. Current demo queue unchanged.
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
{
|
||||
"snapshot": "/tmp/pub-rec-final-review-f5br4ch4",
|
||||
"manifestSha256": "3f8e765bded8bbd66d791f7fb761cb6ee3c438b5318a115baa9cc9c0ec75d2e4",
|
||||
"count": 90,
|
||||
"paths": [
|
||||
"BUILD-LOG.md",
|
||||
"agents/README.md",
|
||||
"agents/darkwing/SOUL.md",
|
||||
"agents/dewey/CONTEXT.md",
|
||||
"agents/dewey/README.md",
|
||||
"agents/dewey/SOUL.md",
|
||||
"agents/dewey/launch.sh",
|
||||
"agents/dewey/validate-sessions.mjs",
|
||||
"agents/dewey/work/wui/BRIEF.md",
|
||||
"agents/dewey/work/wui/DECISIONS.md",
|
||||
"agents/dewey/work/wui/HISTORY.md",
|
||||
"agents/dewey/work/wui/PUBLICATION.md",
|
||||
"agents/dewey/work/wui/README.md",
|
||||
"agents/dewey/work/wui/RESEARCH.md",
|
||||
"agents/dewey/work/wui/TASKS.md",
|
||||
"agents/dewey/work/wui/VERIFY.md",
|
||||
"agents/dewey/work/wui/assets/fonts/dm-sans-400.woff2",
|
||||
"agents/dewey/work/wui/assets/fonts/dm-sans-500.woff2",
|
||||
"agents/dewey/work/wui/assets/fonts/dm-sans-600.woff2",
|
||||
"agents/dewey/work/wui/assets/fonts/dm-sans-700.woff2",
|
||||
"agents/dewey/work/wui/assets/fonts/dm-sans-OFL.txt",
|
||||
"agents/dewey/work/wui/assets/fonts/dm-sans-sources.txt",
|
||||
"agents/dewey/work/wui/assets/fonts/ibm-plex-sans-400.woff2",
|
||||
"agents/dewey/work/wui/assets/fonts/ibm-plex-sans-500.woff2",
|
||||
"agents/dewey/work/wui/assets/fonts/ibm-plex-sans-600.woff2",
|
||||
"agents/dewey/work/wui/assets/fonts/ibm-plex-sans-700.woff2",
|
||||
"agents/dewey/work/wui/assets/fonts/ibm-plex-sans-OFL.txt",
|
||||
"agents/dewey/work/wui/assets/fonts/ibm-plex-sans-sources.txt",
|
||||
"agents/dewey/work/wui/assets/fonts/manrope-400.woff2",
|
||||
"agents/dewey/work/wui/assets/fonts/manrope-500.woff2",
|
||||
"agents/dewey/work/wui/assets/fonts/manrope-600.woff2",
|
||||
"agents/dewey/work/wui/assets/fonts/manrope-700.woff2",
|
||||
"agents/dewey/work/wui/assets/fonts/manrope-OFL.txt",
|
||||
"agents/dewey/work/wui/assets/fonts/manrope-sources.txt",
|
||||
"agents/dewey/work/wui/assets/logos/aperture.svg",
|
||||
"agents/dewey/work/wui/assets/logos/assembly.svg",
|
||||
"agents/dewey/work/wui/assets/logos/relay.svg",
|
||||
"agents/dewey/work/wui/assets/palettes.json",
|
||||
"agents/dewey/work/wui/board.js",
|
||||
"agents/dewey/work/wui/brand.js",
|
||||
"agents/dewey/work/wui/checks/assets.mjs",
|
||||
"agents/dewey/work/wui/checks/browser.mjs",
|
||||
"agents/dewey/work/wui/checks/detail-checks.mjs",
|
||||
"agents/dewey/work/wui/checks/fetch-fonts.py",
|
||||
"agents/dewey/work/wui/checks/final-checks.mjs",
|
||||
"agents/dewey/work/wui/checks/references.mjs",
|
||||
"agents/dewey/work/wui/checks/verify.mjs",
|
||||
"agents/dewey/work/wui/evidence/board-dark-1440.png",
|
||||
"agents/dewey/work/wui/evidence/board-dim-1440.png",
|
||||
"agents/dewey/work/wui/evidence/board-light-1440.png",
|
||||
"agents/dewey/work/wui/evidence/board-light-3440.png",
|
||||
"agents/dewey/work/wui/evidence/board-light-390.png",
|
||||
"agents/dewey/work/wui/evidence/detail-verification.json",
|
||||
"agents/dewey/work/wui/evidence/final-verification.json",
|
||||
"agents/dewey/work/wui/evidence/section-color-ultrawide.png",
|
||||
"agents/dewey/work/wui/evidence/section-components-mobile.png",
|
||||
"agents/dewey/work/wui/evidence/section-identity-light.png",
|
||||
"agents/dewey/work/wui/evidence/section-review-light.png",
|
||||
"agents/dewey/work/wui/evidence/section-typography-light.png",
|
||||
"agents/dewey/work/wui/evidence/verification.json",
|
||||
"agents/dewey/work/wui/index.html",
|
||||
"agents/dewey/work/wui/styles.css",
|
||||
"agents/filbert/CONTEXT.md",
|
||||
"agents/filbert/README.md",
|
||||
"agents/filbert/SOUL.md",
|
||||
"agents/filbert/launch.sh",
|
||||
"agents/filbert/validate-sessions.mjs",
|
||||
"agents/rocko/CONTEXT.md",
|
||||
"agents/rocko/README.md",
|
||||
"agents/rocko/SOUL.md",
|
||||
"agents/rocko/launch.sh",
|
||||
"docs/SESSIONS.md",
|
||||
"docs/TOOLS.md",
|
||||
"docs/plans/2026-09-08_publication-recovery-trial.md",
|
||||
"docs/plans/CURRENT.md",
|
||||
"docs/plans/reviews/2026-09-08_publication-trial-inventory-disposition.md",
|
||||
"docs/plans/reviews/2026-09-08_publication-trial-launcher-approval-receipt.md",
|
||||
"docs/plans/reviews/2026-09-08_publication-trial-launcher-verdict.md",
|
||||
"docs/plans/reviews/2026-09-08_publication-trial-launcher.sha256",
|
||||
"docs/plans/reviews/2026-09-08_publication-trial-recovery-summary.md",
|
||||
"docs/plans/reviews/2026-09-08_publication-trial-recovery-verdict.md",
|
||||
"docs/plans/reviews/2026-09-08_publication-trial-sonnet-r2-verdict.md",
|
||||
"docs/plans/reviews/2026-09-08_publication-trial-sonnet-verdict.md",
|
||||
"docs/plans/reviews/2026-09-08_publication-trial-wui-condition-disposition.md",
|
||||
"docs/plans/reviews/2026-09-08_publication-trial-wui-verdict.md",
|
||||
"docs/plans/reviews/2026-09-08_publication-trial-wui.sha256",
|
||||
"scripts/agent-host-dev.sh",
|
||||
"scripts/agent.sh",
|
||||
"scripts/test-darkwing-launch.mjs",
|
||||
"scripts/test-rocko-launch.mjs"
|
||||
],
|
||||
"baseline": "3b7fd19d087226b1887bf017fc10ef16b044f6aa",
|
||||
"excluded": "all other worktree changes; raw worker records, unreviewed skills and skill deletion, nonallowlisted WUI evidence"
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
2b47053a78aa6d9826282cb0d63cda3e05d7311b6b21dff3cab8078b80b15b3e BUILD-LOG.md
|
||||
2e1f5ec05031ab10372443585861b12b9981ab311bd9c815620d22c1718a4483 agents/README.md
|
||||
08b93c59b4f9ff427deb8c2e8d88daf75e86bdddf61354f108f61cbf1beb5955 agents/darkwing/SOUL.md
|
||||
61d640098d8ad79c9c069ea761c8a50c5f644cb914a253fe037132c61a4c421c agents/dewey/CONTEXT.md
|
||||
908a5e6e9eea2be2b190ba87a7dade4fa6228bea21aec0b09746a5176fdeda06 agents/dewey/README.md
|
||||
b156fd7c76dfe7c8eb421aeed9d3fd1b681456ca96961d5a010cbe8e1ecf0e33 agents/dewey/SOUL.md
|
||||
b6a21d5ae195664612c1dd3f96670934f92025ea100c0e669fa4f7cacd5974f7 agents/dewey/launch.sh
|
||||
d0136b89509edff48aa0e2ee398acb7cc7ccd47255225823e47892c57384e60b agents/dewey/validate-sessions.mjs
|
||||
c71e0c80c5976fbe5048624a7656ed9812164e3969f6ba76c43239e17746d20a agents/dewey/work/wui/BRIEF.md
|
||||
3c86ba0fd6aa894489caf83f6bff8fd94138c3ddd5f5b33858ef21426f8fce65 agents/dewey/work/wui/DECISIONS.md
|
||||
a7ad1f585702886de2d338f530ca5d29130c4acf8682c5d391f1b9e53bf86fe8 agents/dewey/work/wui/HISTORY.md
|
||||
66d036c238553ea200b0236e8bb965de7634d27869221109cbd506cfe4eefbaf agents/dewey/work/wui/PUBLICATION.md
|
||||
e9cac40fe832d36429f02c4b0fa3e50cf63ccf3457b08e0326b8fc1b6c227b49 agents/dewey/work/wui/README.md
|
||||
fcc6d1ec1a35713f1bf765cbe83c9e526a4907d0cd2ce8889a2ef9ed6c54b25d agents/dewey/work/wui/RESEARCH.md
|
||||
04f2624b507109943d5e3ff5732c66d13816313e54a867ac1852341fb90cd309 agents/dewey/work/wui/TASKS.md
|
||||
63e96d72b6afd4eb8058c8b5b6846dbaa1c808dec1054ab23bfb3f5871f78801 agents/dewey/work/wui/VERIFY.md
|
||||
9fea608a947e67020c33cad9a6fe3d60c54119dfb8cff87768a8117a15ed7543 agents/dewey/work/wui/assets/fonts/dm-sans-400.woff2
|
||||
9fea608a947e67020c33cad9a6fe3d60c54119dfb8cff87768a8117a15ed7543 agents/dewey/work/wui/assets/fonts/dm-sans-500.woff2
|
||||
9fea608a947e67020c33cad9a6fe3d60c54119dfb8cff87768a8117a15ed7543 agents/dewey/work/wui/assets/fonts/dm-sans-600.woff2
|
||||
9fea608a947e67020c33cad9a6fe3d60c54119dfb8cff87768a8117a15ed7543 agents/dewey/work/wui/assets/fonts/dm-sans-700.woff2
|
||||
9af36190332437f5ecd09974de43c1f7c77a310a996cdd8ceb25628b458840e1 agents/dewey/work/wui/assets/fonts/dm-sans-OFL.txt
|
||||
89947da00bec2cbcacab815b7e36bf07a635dec41e3ca87a6eb2484a605a4e71 agents/dewey/work/wui/assets/fonts/dm-sans-sources.txt
|
||||
e2291e842cf5af167122a22881a740c7f2dda7716f1e8cd76680264f4a859470 agents/dewey/work/wui/assets/fonts/ibm-plex-sans-400.woff2
|
||||
e2291e842cf5af167122a22881a740c7f2dda7716f1e8cd76680264f4a859470 agents/dewey/work/wui/assets/fonts/ibm-plex-sans-500.woff2
|
||||
e2291e842cf5af167122a22881a740c7f2dda7716f1e8cd76680264f4a859470 agents/dewey/work/wui/assets/fonts/ibm-plex-sans-600.woff2
|
||||
e2291e842cf5af167122a22881a740c7f2dda7716f1e8cd76680264f4a859470 agents/dewey/work/wui/assets/fonts/ibm-plex-sans-700.woff2
|
||||
7e6b2818edbd8f6a01ae80641cc8f16a51080d08fb4e532be3a0b6f74adb07da agents/dewey/work/wui/assets/fonts/ibm-plex-sans-OFL.txt
|
||||
a762adc472b0911c4f5d0e3f0dd672c557c4b3debbc9b617488b46c36e10b183 agents/dewey/work/wui/assets/fonts/ibm-plex-sans-sources.txt
|
||||
a30ddcd349703aff7464c34bef3fffdff405ee50c113440d7c8693c02d210972 agents/dewey/work/wui/assets/fonts/manrope-400.woff2
|
||||
a30ddcd349703aff7464c34bef3fffdff405ee50c113440d7c8693c02d210972 agents/dewey/work/wui/assets/fonts/manrope-500.woff2
|
||||
a30ddcd349703aff7464c34bef3fffdff405ee50c113440d7c8693c02d210972 agents/dewey/work/wui/assets/fonts/manrope-600.woff2
|
||||
a30ddcd349703aff7464c34bef3fffdff405ee50c113440d7c8693c02d210972 agents/dewey/work/wui/assets/fonts/manrope-700.woff2
|
||||
e01b637272e0cbdfb240184dd98ea5cc671556d9894dae2668d92ab2c906787c agents/dewey/work/wui/assets/fonts/manrope-OFL.txt
|
||||
0d9aaaaa963b675d94d8fbee0cf47a8ecf03ea412f8b14aba96416375e5a2bb5 agents/dewey/work/wui/assets/fonts/manrope-sources.txt
|
||||
a1a047eb0b7f9c8f3e656d97d2292545371f8f0a92b4eb273cfd2fc371bd50ad agents/dewey/work/wui/assets/logos/aperture.svg
|
||||
d3d0eb03872b7336b00186beb95567840e5caf2bef29c2a9599480b29eb2f8da agents/dewey/work/wui/assets/logos/assembly.svg
|
||||
446cb7c0b75bb5cc7e3e08d9feb979c000531adfba0523aec81fb9af77f1ae55 agents/dewey/work/wui/assets/logos/relay.svg
|
||||
9efa30b490fa2cde89dcd3c9eafd37ae83a77a84a2a1965c78828e410be2b568 agents/dewey/work/wui/assets/palettes.json
|
||||
31222b6c40af7f253cceccc3d3caef5c2b0f9c0e096ea2eb5828b2224c3c47fe agents/dewey/work/wui/board.js
|
||||
d568df6dca14ae336db3b627639c8181c088649a21ffe992f9bfacc20b5b6238 agents/dewey/work/wui/brand.js
|
||||
e884333a3191921050c6ab45c7d87d40c6bc3092ba9d55c3c06bc5f0d01d5da3 agents/dewey/work/wui/checks/assets.mjs
|
||||
3ff14de07e87cc624433db6425b9d05e40d98f61e40f2bbf1fbee7431f9d73c1 agents/dewey/work/wui/checks/browser.mjs
|
||||
16b3cf3f7c8897dddef3b4caf1e9200272078cea8226a6df5e9ea1e7d25fe598 agents/dewey/work/wui/checks/detail-checks.mjs
|
||||
af924e53a19e3a639e5bc4c1e6a27253d03adcd935a8e1a847806761b797336c agents/dewey/work/wui/checks/fetch-fonts.py
|
||||
fd7d5baad1eb01c41ae98e1341aa5b16bb22e02f5296951381f48705b42d6855 agents/dewey/work/wui/checks/final-checks.mjs
|
||||
df79defbecf1500b6b5abdf7f0568c22ae88b437e841f0c95a7fa16d5d5fd3d2 agents/dewey/work/wui/checks/references.mjs
|
||||
bd6cc0c1021401207519e3489105284d120da2d8b85710e8fd51c1939f10e411 agents/dewey/work/wui/checks/verify.mjs
|
||||
41d4aababef4fdd5beff4f0b75fcdcd59e9a2fdf408a6a7aaf9f7afd86d1ac02 agents/dewey/work/wui/evidence/board-dark-1440.png
|
||||
9599769f4ed18363c3b7c0061823e0fd772d9cd516d3f72ab02e7b74a01de93c agents/dewey/work/wui/evidence/board-dim-1440.png
|
||||
d8097a2896c3c4348f709c1b25609207dad754d051994bc6f4835ed38d2cf290 agents/dewey/work/wui/evidence/board-light-1440.png
|
||||
8f5d62c30b8e6694e53608ba69c841024926c47d3934a76101a722856fa1e890 agents/dewey/work/wui/evidence/board-light-3440.png
|
||||
9e834a3f97bb446155d07f053adceaaeb1907d0397a44f5b31f8c7553d79931c agents/dewey/work/wui/evidence/board-light-390.png
|
||||
093e79080560bed7fdb0577298726613049830d1294f3515bc394dce7e62bcd2 agents/dewey/work/wui/evidence/detail-verification.json
|
||||
769e5e695ddec233323b59d226941edc6d98590b8e896588a92bf3366a2cee65 agents/dewey/work/wui/evidence/final-verification.json
|
||||
4b213ba93554d1651679d3d3189b6c25f799d2d6e88106ff09e109c0bf44685c agents/dewey/work/wui/evidence/section-color-ultrawide.png
|
||||
093f94495b5f4363a89ebb16228997e5c495f877f2ad4f621de2ec5e19acdaac agents/dewey/work/wui/evidence/section-components-mobile.png
|
||||
693de8c423cea8775810be8755ffe8a803215725bc8e9e1c9cb367bd905a1161 agents/dewey/work/wui/evidence/section-identity-light.png
|
||||
ffecc26d0f2e4f4a9c1d907160ca5a5ef9d85c4802c1aa5fd06304a02c7ea60e agents/dewey/work/wui/evidence/section-review-light.png
|
||||
379a5fea56a84bce71cd88995bae3011239f1990d51c5f5a270d7d47238b7ce3 agents/dewey/work/wui/evidence/section-typography-light.png
|
||||
73cd0e1795f2e81d1a5e6ae5068c5dea484dd37410ab233f6e30173a21c93cf7 agents/dewey/work/wui/evidence/verification.json
|
||||
ff0b6a8fd4e8cf5a0e8d3361243b730d83a86a8563562ffb62338b6635965235 agents/dewey/work/wui/index.html
|
||||
4f1309f4b4aec0d595300da060f49f7feb2b3042a8d73468894965ae83b9a04e agents/dewey/work/wui/styles.css
|
||||
485737e40449a2fbc5215fa11357cd2706c3d90265d472a07aa9644d56230fec agents/filbert/CONTEXT.md
|
||||
d3bd85dd59142ca82d8b8a355921389dd1dd9da880c47b7a4760e85e557687e4 agents/filbert/README.md
|
||||
8ab8142d0f118e9635d40e2a44d0497f6a6acf62deb50d5435715644b9c71e01 agents/filbert/SOUL.md
|
||||
6e5d04034e73d9dcacc6797a19b4e64c2d2e4575a3ebbab6ab3aadf86592681f agents/filbert/launch.sh
|
||||
8a7dc4a3f368b0a695ac7d0f7da3f360dd12c7a231f5e7dbe6b576b80b409979 agents/filbert/validate-sessions.mjs
|
||||
ecb5110aa673adefc2168815bdeec577ce18d979585487475b4a429cde0777ba agents/rocko/CONTEXT.md
|
||||
5a97fdb057a331dfe8d4bc7dbc6ab6b93855fc1e194b1c5f0efef784a0a62c4f agents/rocko/README.md
|
||||
d5917650ad98ce6a9e51091d0758121db26877304491c8c00086675f28ffd26b agents/rocko/SOUL.md
|
||||
550ec63aeac4b4b049bd527c157d922626b38373df37debefda54bed8ec26014 agents/rocko/launch.sh
|
||||
bc10acb51bfa92edf6be8ee4cd356690c1614d459288116d4b8e63808a9bc44e docs/SESSIONS.md
|
||||
48c3b026513dc2e4bdcc88f7aac87de5bb6d0fbb8bf45d8b7de60d38a2ed2ffd docs/TOOLS.md
|
||||
a8266a2dde67d71b5e957df78d43a98d0d9308315f5aff8ea3c63f9cdd22fccb docs/plans/2026-09-08_publication-recovery-trial.md
|
||||
0633fd1932ea79c7135acdd20ad00e50ad62b10e9f855f0b38767b6439e53fb3 docs/plans/CURRENT.md
|
||||
929c48a9d3900dca2fd83827d7edf021d0c545f821662dd4a66afaa1772d589a docs/plans/reviews/2026-09-08_publication-trial-inventory-disposition.md
|
||||
5a593f966d756a8797bca631f1573959cf51f7858f54fd25e053d8c2f4e28ffa docs/plans/reviews/2026-09-08_publication-trial-launcher-approval-receipt.md
|
||||
6df113b111e94cd051820c3796221ab3c04abf7fa68e09695cd79c33070bba44 docs/plans/reviews/2026-09-08_publication-trial-launcher-verdict.md
|
||||
8900faf13b3a95918b9542e4b96a57f3561101be7004d74db7b0bb6a7e0a7a5c docs/plans/reviews/2026-09-08_publication-trial-launcher.sha256
|
||||
0e17757cfd3af3bfd3003957550d78c37d32c2b11c75c2b10c76fb9bb5a28a07 docs/plans/reviews/2026-09-08_publication-trial-recovery-summary.md
|
||||
397be934731eb9c2f71f222680a3573dff69d6e37588fc1e8906879a443a7dfc docs/plans/reviews/2026-09-08_publication-trial-recovery-verdict.md
|
||||
f018dd59b184b0d44ae02b83d106ce5b5538b89ceb6297cf7aff2c7093a45453 docs/plans/reviews/2026-09-08_publication-trial-sonnet-r2-verdict.md
|
||||
5bfeb73f254e9a2f7aef8e18a50f0c96b09c3446f21a3f121367c40634521b11 docs/plans/reviews/2026-09-08_publication-trial-sonnet-verdict.md
|
||||
c5649f66c66b60bfcf9c05999d2bfbdf7b93dafee9f6e7ffb8947386b795eb0f docs/plans/reviews/2026-09-08_publication-trial-wui-condition-disposition.md
|
||||
793b556896483ca58dd875a7914731e36c5d5aa83f4e061ddfeb4d4cbe68c535 docs/plans/reviews/2026-09-08_publication-trial-wui-verdict.md
|
||||
a585c1eedb17044962c0419861a1032b23409b769c5d304aceff6ef6089a0e11 docs/plans/reviews/2026-09-08_publication-trial-wui.sha256
|
||||
07f4048729c36c57b6546d3776c81ff85dd89af93666a15b7c41805a336d5d1a scripts/agent-host-dev.sh
|
||||
ddfb43d2599a722452376eee52cbc66da250722f0de55be1570eb55c4d920145 scripts/agent.sh
|
||||
052ad48498102fac2a89047498500b0a3234a87844415b22a1ea70866df63c87 scripts/test-darkwing-launch.mjs
|
||||
7c2395250ca77a841e22099d1bed5800dab594e63c3f29d3cb96f38a1c570788 scripts/test-rocko-launch.mjs
|
||||
@@ -0,0 +1,10 @@
|
||||
# PUB-REC-ROCKO-1 inventory findings — coordinator disposition
|
||||
|
||||
1. TOOLS.md host-dev usage now includes provider/model/thinking flags. Source behavior unchanged; correction needs inclusion in final exact candidate review.
|
||||
2. Added skills/ms-executive-update/README.md publication/compatibility note. Preserve operator-supplied SKILL.md bytes and Codex attribution without claiming a fresh comparison to an unavailable original. Missing fleet paths are not native authority; actual goal_report schema/injected context prevail. No skill activation or historical fixture edits.
|
||||
3. Pi launcher tests now copy only launch.sh, SOUL.md, CONTEXT.md and validate-sessions.mjs instead of recursive agent work/scratch. Assertions verify those subtrees are absent. Fresh coordinator run `node --test scripts/test-darkwing-launch.mjs`: four passed, zero failed, exit 0; log /tmp/pub-rec-pi-launch-tests.log. This is a separate coordinator test, not a repeat of Rocko's reserved post-restart command.
|
||||
4. Claude prompt argv-size limit remains a documented observation, not an observed defect at current size. No runtime redesign in this publication trial.
|
||||
5. Coordinator owns shared session registration for the bounded three-artifact worker task; append-only entries written. No new owner decision required.
|
||||
6. Source review reported no correctness defect; it is not independent final candidate approval. Codex remains recorded author of pending launchers; Jason's newer explicit publication ruling permits reviewed integration without pretending Rocko or Filbert authored them. C1 untouched.
|
||||
|
||||
Raw Rocko inventory/checkpoint contain runtime identifiers and are withheld from publication. Use curated, privacy-reviewed derivatives. They are not silently edited or republished. Both the original reserved Rocko test and launcher remain pinned unchanged after coordinator corrections.
|
||||
@@ -0,0 +1,9 @@
|
||||
# Launcher publication review accepted
|
||||
|
||||
PUB-REC-FILBERT-LAUNCHER-1 independently APPROVED the exact 23 candidates at manifest 8900faf13b3a95918b9542e4b96a57f3561101be7004d74db7b0bb6a7e0a7a5c. Coordinator read the full verdict and recomputed all 57 frozen file hashes plus all 23 live candidate hashes. No drift.
|
||||
|
||||
Filbert independently reports isolated fixture reruns, four Pi tests and one Rocko test passed. These are reviewer fixture executions, not repeats attributed to Rocko's historical recovery invocation. Cosmetic duplicate assignment remains unchanged to preserve approved bytes; argv-size observation remains documented.
|
||||
|
||||
Acknowledgement sent to Filbert on default socket, reaction class. Transport exit 0: transport dispatched; application acceptance unknown. No reply requested.
|
||||
|
||||
Next gate is final selective publication inventory, including privacy-safe review records and exclusions, followed by authorized integration and remote verification. Review does not grant push authority; the existing owner publication mandate governs that act. No deployment, live restart, automated recovery controller or overall trial acceptance inferred. Jason's question about automating testing remains a scope clarification, not new implementation authority.
|
||||
@@ -0,0 +1,35 @@
|
||||
# PUB-REC-FILBERT-LAUNCHER-1 — final launcher candidate verdict
|
||||
|
||||
Reviewer: Filbert (independent). Coordinator: Darkwing. Original launcher authorship: Codex (session history); coordinator corrections: test fixture narrowing, TOOLS.md flags, skill compatibility note.
|
||||
|
||||
Independence: I authored none of the 23 candidates; the `agents/filbert/` seat files describe my seat but were written by Codex. No conflict.
|
||||
|
||||
## Verdict: APPROVED for publication
|
||||
|
||||
Exact candidate: the 23 candidatePaths of snapshot `/tmp/pub-rec-launcher-review-a35yzs12`, manifest SHA-256 `8900faf13b3a95918b9542e4b96a57f3561101be7004d74db7b0bb6a7e0a7a5c` (57 files including dependencies). All 57 hashes verified before and after review; snapshot unchanged. Dependencies supplied context only; this verdict does not publish them. The approved WUI draft and recovery summary are separate approvals and are not folded in here.
|
||||
|
||||
This grants no deployment, live-launch, or push authority. Jason retains final trial acceptance.
|
||||
|
||||
## Independent checks and results
|
||||
|
||||
- Syntax: `bash -n` on five shell candidates and `node --check` on both test files and all three `validate-sessions.mjs` copies: pass. The three validator copies differ only in the agent name in the error string, as claimed.
|
||||
- Fixture reruns, in my disposable copy (separate from Rocko's recorded historical recovery action and from the coordinator's run): `node --test scripts/test-darkwing-launch.mjs` — 4 tests, 4 pass, 0 fail, exit 0; `node --test scripts/test-rocko-launch.mjs` — 1 test, 1 pass, 0 fail, exit 0. Logs: `/tmp/filbert-launcher-vkdzSG/`.
|
||||
- Pinned continuity: rocko test `13c32cad…`, rocko launcher `b65566e1…`, and `skills/ms-executive-update/SKILL.md` `368a8576…` are byte-identical to the values pinned in the recovery review and inventory. Coordinator corrections did not touch them.
|
||||
- Isolation of both fixtures confirmed by full source read: temp roots, fake capture-only `pi`/`claude`, stubbed `common.sh`/`sync-dev-extensions.sh`/`docker`, fixture contracts; the Pi fixture now copies only `launch.sh`, `SOUL.md`, `CONTEXT.md`, `validate-sessions.mjs` per agent and asserts `work/` and `scratch/` absent (the coordinator's narrowing, verified in source and by rerun).
|
||||
- Branch separation: `--host-dev` is a leading explicit mode only; container refusals never fall back to host. Container path keeps config gating, fail-closed auth resolution (data-root-managed, non-symlink, 0600), role ceilings, skill enablement, workspace naming.
|
||||
- Refusals: host mode rejects container flags (`--auth`/`--mission`/`--tools` land on the unknown-argument refusal; TOOLS.md documents this), invalid names, flag-like values, invalid thinking levels, non-TTY, second concurrent TUI (flock), damaged or foreign-workspace session history, and empty/missing context files. All exercised by the fixtures I reran.
|
||||
- Config/auth isolation: host mode uses native Pi authentication and copies no credentials; `--check` creates no `.pi/state` (asserted by the fixture).
|
||||
- Session semantics: first launch starts a conversation; resume validates JSONL structure and workspace match before `--continue`; `--fresh` preserves earlier history; every launch writes a hashed private context snapshot.
|
||||
- Documentation consistency: TOOLS.md host-dev usage now includes `--provider/--model/--thinking` matching `agent-host-dev.sh`; `agents/README.md` wrapper/override description matches the actual wrappers (Filbert's appends provider/model/thinking); per-seat READMEs match launcher behavior.
|
||||
- Skill note: `skills/ms-executive-update/README.md` accurately preserves Codex/operator provenance without claiming a fresh byte comparison, flags the dangling fleet-layout references, defers to the actual goal_report schema, and states the skill is not loaded by the host-dev launcher (confirmed: it is not in the ten-skill list). Publication does not activate it.
|
||||
- Publication safety scan of all 23 candidates: no session UUIDs, hosted conversation links, home paths, token/credential shapes, or socket names. `.pi/state` mentions are generic path documentation. The canonical checkout path is already-public posture per the inventory.
|
||||
|
||||
## Findings (non-blocking)
|
||||
|
||||
1. Cosmetic: `scripts/agent.sh` initializes `AGENT_DEF_SKILLS=""` twice in immediate succession (lines 98–99). Dead assignment, re-initialized before use; no behavioral effect. Fix at leisure in a future reviewed change, not a publication blocker.
|
||||
2. Argv observation assessed, not redesigned: `agents/rocko/launch.sh` passes the context snapshot as a single argv value. Current inputs are a few KB against a megabyte-scale argv limit; it stays a documented scalability observation (inventory issue 4) with no unobserved redesign.
|
||||
3. Context note: the compatibility-symlink home path appears only in a dependency README (`agents/darkwing/README.md`), not in any candidate; existing published posture already includes such paths.
|
||||
|
||||
## Publication boundary
|
||||
|
||||
Publish exactly the 23 candidatePaths at the verified manifest. Dependencies (34 paths) supplied review context only. Raw worker records with runtime identifiers remain local per the recovery verdict. Any candidate change requires a new review.
|
||||
@@ -0,0 +1,57 @@
|
||||
db5bde2f586dc420e16497bb6b441ee7ec366b049a6416fe30c415f81b8d4c13 AGENTS.md
|
||||
f1ae5988b04cf1680d2eeefad23c119520ec365491c563237f7488242e10b925 agents/README.md
|
||||
31d5783fc47dac85cd0e7549100d0d7a8f8af239ed75852741f1aca9fb2411a9 agents/darkwing/CONTEXT.md
|
||||
7b37d7a239ecd44fe6258b6cf966d682901ee35a2f00bdf10b19e6d4fedccec4 agents/darkwing/README.md
|
||||
87e6ee7459f705cfb0c354cccade74280feb05408187c52cbf92b9011c370783 agents/darkwing/SOUL.md
|
||||
67a4e63d3ca78f80e39d9076443dd24d2a3443ff6075b850d43fb62ccd806c9a agents/darkwing/launch.sh
|
||||
a4172eeb05110e225c716e708a9f1ed72b1d361dc12ac1d7fb4665c00fd4a21f agents/darkwing/validate-sessions.mjs
|
||||
c583a3349025f3220b42fd8eee9281ead67f0755715d5e8d05f8584c8e3ddf73 agents/darkwing/work/RESTART.md
|
||||
61d640098d8ad79c9c069ea761c8a50c5f644cb914a253fe037132c61a4c421c agents/dewey/CONTEXT.md
|
||||
908a5e6e9eea2be2b190ba87a7dade4fa6228bea21aec0b09746a5176fdeda06 agents/dewey/README.md
|
||||
b156fd7c76dfe7c8eb421aeed9d3fd1b681456ca96961d5a010cbe8e1ecf0e33 agents/dewey/SOUL.md
|
||||
b6a21d5ae195664612c1dd3f96670934f92025ea100c0e669fa4f7cacd5974f7 agents/dewey/launch.sh
|
||||
d0136b89509edff48aa0e2ee398acb7cc7ccd47255225823e47892c57384e60b agents/dewey/validate-sessions.mjs
|
||||
485737e40449a2fbc5215fa11357cd2706c3d90265d472a07aa9644d56230fec agents/filbert/CONTEXT.md
|
||||
d3bd85dd59142ca82d8b8a355921389dd1dd9da880c47b7a4760e85e557687e4 agents/filbert/README.md
|
||||
8ab8142d0f118e9635d40e2a44d0497f6a6acf62deb50d5435715644b9c71e01 agents/filbert/SOUL.md
|
||||
6e5d04034e73d9dcacc6797a19b4e64c2d2e4575a3ebbab6ab3aadf86592681f agents/filbert/launch.sh
|
||||
8a7dc4a3f368b0a695ac7d0f7da3f360dd12c7a231f5e7dbe6b576b80b409979 agents/filbert/validate-sessions.mjs
|
||||
e31c80e007d8b890c698048feb64c0f1fba9cf77f4836e007b9a9b7538b2d851 agents/rocko/CONTEXT.md
|
||||
1576c37d8810231c65d3306c75667a632e5662062ee43f67cb43b01302e10ee5 agents/rocko/README.md
|
||||
d5917650ad98ce6a9e51091d0758121db26877304491c8c00086675f28ffd26b agents/rocko/SOUL.md
|
||||
b65566e19fa0fb83409552954a645b8cdc4d2bdb1002df55d27088add6acf65d agents/rocko/launch.sh
|
||||
ca48e94ab814149f7a40f44bb8fce14f29215722f7a09d991186b3780fb2032b contracts/CONSTITUTION.md
|
||||
2bdb3abb4cd6c13e2f1ddcd55b07f19ef69d3528738922c7473d16fc74072a7f contracts/SOUL.md
|
||||
9e383354be38d0ea011b1145b6b3a4f35bfae6ebd856dc7921b8bae2959382e0 contracts/STANDARDS.md
|
||||
48c3b026513dc2e4bdcc88f7aac87de5bb6d0fbb8bf45d8b7de60d38a2ed2ffd docs/TOOLS.md
|
||||
6aecf9ea47b99267b7795eeecdedc53845e6834f0d7445481374b808e395ceb0 package.json
|
||||
07f4048729c36c57b6546d3776c81ff85dd89af93666a15b7c41805a336d5d1a scripts/agent-host-dev.sh
|
||||
ddfb43d2599a722452376eee52cbc66da250722f0de55be1570eb55c4d920145 scripts/agent.sh
|
||||
40213f2c3329ad6985d9915c507f96bada97db720454d603505dc57f2b9d4136 scripts/common.sh
|
||||
052ad48498102fac2a89047498500b0a3234a87844415b22a1ea70866df63c87 scripts/test-darkwing-launch.mjs
|
||||
13c32cad02587aad85da2f1a2bca8e61d77d9285ffc9e21dc91b7bafa7d0e05d scripts/test-rocko-launch.mjs
|
||||
fd8e77a9f32142d35cfbf4408875ce70d6edbb60888e75c935763883ef853cfb skills/ms-agent-watch/SKILL.md
|
||||
f3ce97bdbd642beb5b2e5b74d3529041d475a5bf42b9a1e0936334c2d1edcf43 skills/ms-agent/SKILL.md
|
||||
06991caef7806dfc88cd7cdf02c744475f4397230ed8a2e94e89c0178a5b4bc0 skills/ms-archify/SKILL.md
|
||||
4c887c0d207901104eb7f8700158345521dc0b8e088c57ce5f0b19152cb088f5 skills/ms-communications/SKILL.md
|
||||
d7aae586ede3ae1e867b60ec0a4040e8d0dad8b128cc9fa8d20228eb512381d1 skills/ms-conductor/SKILL.md
|
||||
2b683dd50c07aa472451c080a0f2c7087f1ec08690eac86bed17c8f9fb2878f3 skills/ms-executive-update/README.md
|
||||
368a857632dfd118a11a752ae0a775ca13d6837cf05d8f870946c9e7364d127f skills/ms-executive-update/SKILL.md
|
||||
28f9b76bb89f8aadfb3b8933255c54e360af741b050a7738cb0a904f7835a95e skills/ms-file-read/SKILL.md
|
||||
ad9ee2d00b87b2c6fa36b7863c0034b8883f7e1fa2aa5390e67121eda0165e14 skills/ms-file-write/SKILL.md
|
||||
885e993a6bd3c4d6ce94b0d95a8c82e212be78c5c727035c81f3dbed39b0ceee skills/ms-frontend-design/SKILL.md
|
||||
b754f2f428bf0107aea4d5dffb0d148d83fa9d71dfc22cee5b31007ede26f884 skills/ms-frontend-design/references/accessibility.md
|
||||
9232279ec748ec7076566b57d6e8da6f35d06cb9de58d9080cdea66172b2a41c skills/ms-frontend-design/references/design-principles.md
|
||||
a77c2ecc434a77786985f2a1aa01e5c17c43f566688aeda3909506bd9641690a skills/ms-frontend-design/references/site-completeness.md
|
||||
94782abd9d0834d1b37b2609782405777c65d42fc60f3651e01f46a9c88cfd5c skills/ms-frontend-design/references/verification.md
|
||||
558739ad5d5a22fa35f31049829b5c92971f693d10f91450da2bc381d6c0adaf skills/ms-frontend-design/references/visual-system.md
|
||||
eb9e56cae2647b6553736a87af2f4ed89adb02e0a3220637ff84dce19bea8b3f skills/ms-goal/SKILL.md
|
||||
ea9196042355b08f9e43eaa67d62c82419ad9768666a9f56b815184a3f48997d skills/ms-goal/references/execution-checks.md
|
||||
bfce50bee7c92b15e3edd9399d1646bed8ea77b1a768747dfd185faa0387b114 skills/ms-grill-me/SKILL.md
|
||||
9f7bc752825842808b8d206f0386aac89113066474d803de02550f9bb83b09c2 skills/ms-grill-me/upstream-grill-me.md
|
||||
6fc326fa6acfb254877812a833fb3b49c6d7b9c5b8246d18f178ef411b60a7e7 skills/ms-grill-me/upstream-grilling.md
|
||||
0132ad6508df2bcba0df7fb417e06cbe90c7ea663e334f2176c8973757bb4809 skills/ms-proactive-agent/SKILL.md
|
||||
f81aa1adf33f9d46f9783df3eeec9f705c5b65c37d48d7708cdb923eac0c5478 skills/ms-sdlc/SKILL.md
|
||||
3b78c1f75d23fd7a17f590c02f570a356fd7cbc5b031eca849bd04a873efe6f7 skills/ms-tools/SKILL.md
|
||||
0eace7c537ae711876cc82137aa5e4f84f1a2145676de8cfb2fe963f32efb530 skills/ms-unslop/SKILL.md
|
||||
2eae928c488ea9ae752b19cb72fa532ea50f5306653684320d396ab2b0473e8a skills/ms-user/SKILL.md
|
||||
@@ -0,0 +1,28 @@
|
||||
# Planned-restart trial — privacy-safe recovery summary
|
||||
|
||||
Task PUB-REC-ROCKO-1, trial #1497. Author of worker evidence: Rocko. Coordinator: Darkwing. Status: worker action complete; independent recovery review and Jason's overall trial acceptance pending.
|
||||
|
||||
## Evidence chain
|
||||
|
||||
1. Before restart, Rocko declared an unexecuted next action: `node --test scripts/test-rocko-launch.mjs`, inspected as an isolated fixture with fake Claude and temporary state, no real model call. Coordinator independently read the test without running the reserved action.
|
||||
2. Coordinator verified checkpoint and inventory hashes, unchanged test/launcher bytes, baseline HEAD and absent recovery artifact before telling Jason the planned restart was ready.
|
||||
3. Jason reported `done`, then `continue issued`. Coordinator supplied no reconstructed task prompt after restart and did not read private sessions/panes.
|
||||
4. Rocko reports retained task context, re-reading declared shared records, no private-state reads after restart and one reserved test invocation. Launcher resume stdout was unavailable inside his process; exact resume mode is inferred from retained context, not independently observed from that output. Harness compaction occurred and was not treated as the sole task record.
|
||||
5. Worker output reports one test, one pass, zero failures, exit 0, empty stderr. No tracked files changed; two additional untracked task records appeared, including the worker recovery file and an unrelated coordinator review disposition. This is not a literally unchanged worktree claim.
|
||||
6. The coordinator verified test and launcher hashes still match the pre-restart inventory. The announced recovery hash matches exactly the byte prefix before its appended transport receipt; the full post-send record has a different, recorded identity.
|
||||
|
||||
## Exact identities
|
||||
|
||||
- Baseline HEAD: 3b7fd19d087226b1887bf017fc10ef16b044f6aa.
|
||||
- Checkpoint SHA-256: 30c4e1906b22220a29868c1ef4253676d2e2324d46a1f281543e50347af7fdd8.
|
||||
- Inventory SHA-256: 51536b1d4a8fee30caa711527295ed7b860d46ae9b81e5530af6631a53030b5f.
|
||||
- Recovery announced pre-send SHA-256: 52778f1a681277335f5d86a1e1fe2b96e9df07303b81c1d833ed674cf44811f7.
|
||||
- Recovery full post-send SHA-256: df77133d49d66be72f12f6d742d1f220529a82098efac79117c13d256048abca.
|
||||
- Test SHA-256: 13c32cad02587aad85da2f1a2bca8e61d77d9285ffc9e21dc91b7bafa7d0e05d.
|
||||
- Launcher SHA-256: b65566e19fa0fb83409552954a645b8cdc4d2bdb1002df55d27088add6acf65d.
|
||||
|
||||
Raw worker records remain local pending privacy handling; they contain runtime identifiers and are not publication candidates. This derivative deliberately omits those identifiers and hosted conversation links. Hashes identify evidence without publishing private session state.
|
||||
|
||||
## Limits
|
||||
|
||||
A planned operator restart with neutral continuation and checkpoint recovery is supported by the owner report and worker execution evidence. No crash-recovery guarantee, authenticated process-incarnation proof, production orchestration, repeated reliability rate or unobserved exactly-once guarantee is claimed. One execution is the worker's recorded run count, not a separate runtime-enforced invariant. Independent review must evaluate the evidence and these limits before publication. C1 remains held. Candidate review, publication and overall user acceptance are separate gates.
|
||||
@@ -0,0 +1,47 @@
|
||||
# PUB-REC-FILBERT-RECOVERY-1 — independent recovery-evidence verdict
|
||||
|
||||
Reviewer: Filbert (independent). Worker evidence: Rocko. Coordinator and curated derivative: Darkwing. Trial #1497.
|
||||
|
||||
Independence: no authorship or review role in the checkpoint, inventory, restart, or summary; no conflict. This verdict is not the final launcher code review and not Jason's trial acceptance.
|
||||
|
||||
## Verdicts
|
||||
|
||||
1. Bounded planned-checkpoint recovery criterion (a useful development assignment survives one planned participating-agent restart without the owner reconstructing its briefing): **SUPPORTED**, with the inference and observation limits recorded below.
|
||||
2. Publishing the curated privacy-safe summary `docs/plans/reviews/2026-09-08_publication-trial-recovery-summary.md`: **APPROVED** as reviewed, under the conditions in the last section.
|
||||
|
||||
## Admission and integrity
|
||||
|
||||
Snapshot `/tmp/pub-rec-recovery-review-4em3lt1p`: SHA256SUMS hashes to the declared `b52a621551c9e6390a2ed3bb4d80431acd81e897b90660e60798d33767b0b5b1`; all ten files verify; path set exact; snapshot read-only and left unchanged. Review was reading and hashing only: no launcher/test execution (the reserved action was not rerun as a substitute for historical evidence), no private runtime/pane/transcript reads, no hosted session links followed.
|
||||
|
||||
## Independently verified facts
|
||||
|
||||
- Hash continuity, recomputed by me inside the snapshot: trial plan `ab908308…`, task `af673b60…`, checkpoint `30c4e190…`, inventory `51536b1d…`, recovery full record `df77133d…`, reserved test `13c32cad…`, launcher `b65566e1…`. All match every place they are quoted (checkpoint sections 1/3, readiness admission, recovery sections 1/3, summary identities).
|
||||
- The announced pre-send recovery hash `52778f1a…` reproduces exactly as the byte prefix ending immediately before the appended delivery paragraph in section 6. The summary's prefix-claim is literally true, not rhetorical.
|
||||
- The reserved action was declared before the restart and unexecuted at restart time: the checkpoint reserves `node --test scripts/test-rocko-launch.mjs`, and the operator restart receipt independently records the recovery artifact absent and no execution inferred; the coordinator readiness record confirms the test was read but not run before restart.
|
||||
- The reserved test is genuinely isolated: I read `scripts/test-rocko-launch.mjs` in full. It builds a `mkdtemp` root, copies only `agents/rocko`, writes fixture contracts/AGENTS/USER and a stub `common.sh`, fronts PATH with a fake capture-only `claude`, drives the launcher under `script(1)`, and removes the temp root in `finally`. It never reads real config, the data root, the checkout's `.pi/state`, or a model. One test function, matching the recorded `# tests 1`.
|
||||
- The recovery record's verbatim output (1 pass, 0 fail, exit 0, empty stderr, `ℹ` reporter prefix) is internally consistent with Node 26's reporter and the checkpoint's declared expectation; the record correctly classifies the `ℹ`-versus-`#` difference as formatting, not a count deviation.
|
||||
- The curated summary contains no runtime identifiers: no session UUID, hosted link, socket name, or launch-receipt name (scanned). Its hashes-without-contents approach is the right privacy shape.
|
||||
|
||||
## Reported facts, correctly not overstated
|
||||
|
||||
- The restart and neutral `continue` are owner-reported (`done` per the operator receipt); the coordinator supplied no reconstructed briefing and did not read private state. I did not observe the process.
|
||||
- Resume mode is inferred from retained context (same hosted link and prior conversation); launcher stdout is unobservable from inside the resumed process, and post-restart private-state reads were correctly not performed to confirm it. Normal-resume failure: none reported; no assisted recovery used.
|
||||
- One execution is the worker's recorded run count, not a runtime-enforced invariant; exactly-once is unobserved. Worktree preservation (HEAD unchanged, index empty, only two new untracked task records, no tracked change) is worker-reported with coordinator-side hash agreement; the summary already refuses to call it a literally unchanged worktree claim.
|
||||
- Single planned trial: no crash-recovery, reliability-rate, incarnation-authentication, or orchestration guarantee is claimed, and none may be inferred.
|
||||
|
||||
## Procedural deviations and their handling (preserved, not erased)
|
||||
|
||||
- Appended hash receipts: both the checkpoint and the recovery record append delivery paragraphs after announcing pre-send hashes; both record pre- and post-send identities explicitly, and the checkpoint carries an appended timestamp correction (send ~18:45 UTC, not 18:53) rather than a rewrite. Handled honestly.
|
||||
- Stale A9 statement: the checkpoint's conflict-check paragraph says the inspector package "awaits owner acceptance"; the coordinator ruled that stale (A9 already accepted) rather than an open gate. The stale sentence remains in the raw record with the correction beside it; the derivative does not propagate it.
|
||||
- Own-session metadata reads: before restart the worker read its own session pointer, launch-receipt directory name, and hosted link, which a literal "no private state" reading would exclude. The inventory discloses it, the coordinator ruling preserves the honest qualification, and the summary scopes its no-private-read claim to after restart, which is accurate.
|
||||
- Registration delegation: the worker followed its three-artifact write boundary and did not append to SESSIONS/BUILD-LOG; the coordinator took registration ownership by ruling. A deviation from the root AGENTS.md default, resolved explicitly rather than silently.
|
||||
|
||||
The curated summary accurately reflects the raw evidence on every point I could check, and its limits paragraph matches my own findings. Omissions (checkpoint pre-send hash evolution, A9 note, registration detail) are simplifications that do not misstate anything and remain available in the preserved local raw records.
|
||||
|
||||
## Conditions
|
||||
|
||||
1. Publish the curated summary byte-as-reviewed, SHA-256 `0e17757cfd3af3bfd3003957550d78c37d32c2b11c75c2b10c76fb9bb5a28a07`; any edit requires re-review. The raw recovery record (`df77133d…`) is evidence, not a publication unit.
|
||||
2. Raw checkpoint/inventory/recovery records stay local pending privacy handling; they contain runtime identifiers and are not publication candidates.
|
||||
3. Present the outcome as one bounded planned-checkpoint recovery, not trial acceptance, not crash recovery, and not a reliability claim; the final launcher candidate review and Jason's overall trial acceptance remain separate gates.
|
||||
|
||||
Evidence: frozen snapshot above; all checks offline and read-only. No git operations, source edits, live-seat mutation, or operator actions performed.
|
||||
@@ -0,0 +1,26 @@
|
||||
# PUB-REC-FILBERT-SONNET-2 — focused frozen-delta verdict (round 2)
|
||||
|
||||
Reviewer: Filbert (independent). Coordinator: Darkwing. Supersedes the round-1 REQUEST CHANGES at `2026-09-08_publication-trial-sonnet-verdict.md`, which remains on record unchanged.
|
||||
|
||||
## Verdict: APPROVED
|
||||
|
||||
The SONNET-F1/F2 repairs are exactly the three one-line wording replacements requested, and nothing else changed. Model wording is now consistent across every candidate that mentions Rocko's runtime.
|
||||
|
||||
## What was verified
|
||||
|
||||
- Snapshot `/tmp/pub-rec-sonnet-r2-htbgwodg`: manifest SHA-256 `c5ad630615f67c4480c23f3478123c7c1c5e7c6095bcfa45039650c8213c38bf`, all seven files verify. Structure matches the declaration: four files byte-identical to round 1 (`launch.sh`, rocko `README.md`, rocko `SOUL.md`, test), `CONTEXT.md` further repaired, and the two team files newly included.
|
||||
- Repairs confirmed as minimal single-line deltas:
|
||||
- `agents/rocko/CONTEXT.md`: "using the Fable model" → "using the Sonnet model" (the launch-injected line; SONNET-F1 closed).
|
||||
- `agents/README.md`: team table cell "Claude Code, Fable model" → "Claude Code, Sonnet model" (SONNET-F2a closed).
|
||||
- `agents/darkwing/SOUL.md`: "Rocko (Claude Code with Fable)" → "Rocko (Claude Code with Sonnet)" (SONNET-F2b closed).
|
||||
- No `fable` reference remains in any of the seven files; `sonnet` wording is consistent with the launcher's `--model sonnet` and the test expectation.
|
||||
- Exactly six candidate files differ from the original approved launcher snapshot; `agents/rocko/SOUL.md` is unchanged fixture context.
|
||||
- Combined fixture rerun in a disposable harness (seven R2 files over the approved snapshot's dependency set, isolation previously source-verified): `node --test scripts/test-rocko-launch.mjs scripts/test-darkwing-launch.mjs` — 5 tests, 5 pass, 0 fail, exit 0. This reproduces the coordinator's 5/5 independently; fake model fixtures only.
|
||||
- Historical evidence preserved: the frozen recovery snapshot still pins the fable-era test/launcher bytes, the round-1 rejected verdict is untouched, and no live session was restarted.
|
||||
- All three frozen snapshots re-verified unchanged after review. No private state, live launch, configuration change, source edit, or deployment.
|
||||
|
||||
## Publication effect
|
||||
|
||||
Publish the six changed candidates as these reviewed bytes, replacing their prior approved versions; the remainder of PUB-REC-FILBERT-LAUNCHER-1's approval stands unchanged. Any further candidate change requires new review. Publication review only — no trial acceptance, deployment, or push authority implied.
|
||||
|
||||
Evidence: disposable harness and combined test log under `/tmp/filbert-sonnet-r2-*`.
|
||||
@@ -0,0 +1,31 @@
|
||||
# PUB-REC-FILBERT-SONNET-1 — focused frozen-delta verdict
|
||||
|
||||
Reviewer: Filbert (independent). Coordinator: Darkwing. Owner change: Jason switched Rocko's launcher to Sonnet and authorized matching documentation repairs.
|
||||
|
||||
## Verdict: REQUEST CHANGES
|
||||
|
||||
The three changed files are correct, minimal, and internally matched, and my isolated test rerun passes. The review criterion was model/docs/test consistency, and that criterion is not met across the candidate set: three stale `Fable` references survive, one of them inside this very snapshot.
|
||||
|
||||
## What was verified
|
||||
|
||||
- Snapshot `/tmp/pub-rec-sonnet-review-u__t4rsb`: manifest SHA-256 `52a1c408aad20b8c71377db2e456a11450b1d72264adaa679a26f9374c48e263`, all five files verified before and after review.
|
||||
- Delta versus the approved launcher snapshot `/tmp/pub-rec-launcher-review-a35yzs12` is confined to exactly three files, each changed only in model wording:
|
||||
- `agents/rocko/launch.sh`: banner echo and `exec claude --model sonnet`.
|
||||
- `scripts/test-rocko-launch.mjs`: test title and expected-model assertion.
|
||||
- `agents/rocko/README.md`: three wording lines.
|
||||
- `agents/rocko/SOUL.md` and `agents/rocko/CONTEXT.md` are byte-identical to the approved snapshot (no unrelated changes).
|
||||
- `bash -n` and `node --check` pass. Isolated fixture rerun in a disposable copy (isolation re-confirmed by source read; fake capture-only claude, temp root): `Rocko uses Sonnet…` 1 test, 1 pass, 0 fail, exit 0.
|
||||
- Original recovery evidence untouched: the frozen recovery snapshot still pins test `13c32cad…` and launcher `b65566e1…`; the historical record keeps its original bytes and meaning.
|
||||
- No live launch, private-state read, configuration edit, or deployment.
|
||||
|
||||
## Findings
|
||||
|
||||
1. **SONNET-F1 (blocking): `agents/rocko/CONTEXT.md` still says Fable.** Line 4: "Stack repository, using the Fable model." This file is in the reviewed five-file snapshot and is injected into Rocko's system context at every launch, so the seat would be told it runs Fable while the launcher now execs `--model sonnet`. A one-line repair in this same file completes the declared docs fix.
|
||||
2. **SONNET-F2 (blocking for the combined publication): stale Fable references in two previously approved launcher candidates.** `agents/README.md` team table says "Claude Code, Fable model"; `agents/darkwing/SOUL.md` says "Rocko (Claude Code with Fable)". Those bytes were approved when they matched the fable launcher; publishing them unchanged alongside the sonnet launcher creates factual contradictions in the published team documentation. Each is a small wording repair, but they are revised bytes outside this delta and need their own review coverage (a focused addendum like this one is sufficient).
|
||||
3. Non-blocking note: the coordinator's 1/0 test result was independently reproduced rather than trusted.
|
||||
|
||||
## Required to convert this to approval
|
||||
|
||||
A refreshed delta containing: the same three files as reviewed here plus the `CONTEXT.md` line fix, plus the `agents/README.md` and `agents/darkwing/SOUL.md` wording repairs (or an explicit owner decision to describe Rocko's model generically in team docs). I will re-verify hashes and rerun the isolated test; no other re-review is needed if the delta stays this narrow.
|
||||
|
||||
Evidence: disposable-copy test log and diffs under `/tmp/filbert-sonnet-*`; frozen snapshots unchanged after review. This is publication review only; no trial acceptance, deployment, or push authority implied.
|
||||
@@ -0,0 +1,13 @@
|
||||
# WUI publication approval conditions — coordinator disposition
|
||||
|
||||
Read Filbert's complete PUB-REC-FILBERT-WUI-1 APPROVED verdict for the exact 53-file manifest a585c1ee. Fresh independent browser results are Filbert's measured evidence, not new Darkwing reruns.
|
||||
|
||||
WUI-PUB-F1: retain the exact author bytes. BRIEF.md names Jason Woltje as owner; the full name is already public as repository owner. Boundary's first-name-only description was incomplete. This correction does not broaden permission for unrelated personal information.
|
||||
|
||||
WUI-PUB-F2: retain the historical design-feedback wording in DECISIONS.md rather than silently paraphrasing the immutable reviewed record. It is ordinary candid feedback on a proposed mark, within the owner-approved curated draft publication scope. Separate publication note explains that working feedback is not product messaging or acceptance. No change to the 53-file pin.
|
||||
|
||||
Added coordinator publication label: agents/dewey/work/wui/PUBLICATION.md. It is an explicit additional documentation artifact, not a falsely claimed member of the reviewed 53 files. Names pending owner acceptance, old provisional defaults versus later feedback, font-license limits and excluded historical evidence.
|
||||
|
||||
Visual-check correction: the review's statement that prior coordinator visual inspections supported its structural checks was premature. Darkwing had not inspected the PNGs before that verdict. After receipt, Darkwing used image reads to inspect all ten allowlisted screenshots: board-dark-1440, board-dim-1440, board-light-1440, board-light-3440, board-light-390, section-color-ultrawide, section-components-mobile, section-identity-light, section-review-light, section-typography-light. Observed prototype controls, branding proposals and synthetic specimen content; no private application data or browser chrome observed. Ultrawide images were displayed downscaled; this is bounded visible-content inspection, not exhaustive forensic image analysis. Reviewer visual-pixel NOT RUN remains true for Filbert's own review.
|
||||
|
||||
Owner reports restart complete and neutral `continue` issued. No assignment facts or checkpoint paths were supplied in that continuation. Rocko recovery result remains pending separately; WUI approval does not establish restart success or overall trial acceptance.
|
||||
@@ -0,0 +1,61 @@
|
||||
# PUB-REC-FILBERT-WUI-1 — independent draft-publication verdict
|
||||
|
||||
Reviewer: Filbert (independent). Author: Dewey. Coordinator: Darkwing. Trial: #1497.
|
||||
|
||||
Verdict: APPROVED for draft publication at manifest SHA-256 `a585c1eedb17044962c0419861a1032b23409b769c5d304aceff6ef6089a0e11`, 53 files, snapshot `/tmp/pub-rec-wui-review-cgfkxmll`.
|
||||
|
||||
Independence: no prior authorship or review role in the WUI; no conflict to report. Publication approval only. This approves no branding, product acceptance, license choice, commit, push, or deployment.
|
||||
|
||||
## Admission and integrity
|
||||
|
||||
- All 53 snapshot hashes verified against SHA256SUMS; the manifest file itself hashes to the declared `a585c1ee...` and matches the durable copy at `docs/plans/reviews/2026-09-08_publication-trial-wui.sha256`.
|
||||
- Snapshot path set is exactly the manifest set; no extra files. Snapshot is read-only and re-verified unchanged after review (0 mismatches). All browser checks ran on a disposable copy; no snapshot or author file was mutated.
|
||||
|
||||
## Standalone draft usability
|
||||
|
||||
- Every runtime dependency resolves inside the manifest: index.html uses styles.css, brand.js, board.js, assets/logos/assembly.svg and RESEARCH.md; styles.css loads the 12 bundled woff2 files. No external URL, CDN, fetch, or network call exists in any HTML/CSS/JS/SVG/palette file.
|
||||
- README/VERIFY references to excluded evidence outputs are historical documentation references; the draft needs none of them to function. Nothing excluded was added.
|
||||
- Fresh rerun of the final checks confirms the entry page loads only local `file:` resources.
|
||||
|
||||
## Publication safety
|
||||
|
||||
- Notes contain no credentials, tokens, authentication material, home paths, family/personal data, or private correspondence beyond curated owner feedback (a declared category). The incidental transport identifier and repo-local paths are declared categories.
|
||||
- Screenshots: valid PNGs, no metadata or text chunks, no suspicious embedded strings, dimensions match the claimed viewports.
|
||||
- Two coordinator-judgment notes, neither blocking:
|
||||
- WUI-PUB-F1: BRIEF.md carries the operator's full name "Jason Woltje"; the boundary declared only the first name. The name is already public as repository owner. Keep or addendum is the coordinator's call.
|
||||
- WUI-PUB-F2: DECISIONS.md quotes the owner's candid logo feedback verbatim. It is declared design feedback and factual, but publication wording is an owner-taste decision; paraphrase via label/addendum is acceptable if preferred.
|
||||
- Bounded NOT RUN: independent visual inspection of screenshot pixel content (this reviewer session cannot render images). Structural checks above plus the author's and coordinator's recorded visual inspections stand in; residual risk is low but not zero.
|
||||
|
||||
## Font provenance
|
||||
|
||||
- Three families, each with its own distinct OFL 1.1 notice carrying the correct copyright line; IBM's declares Reserved Font Name "Plex".
|
||||
- Each `*-sources.txt` records the exact Google Fonts CSS/woff2 URLs and upstream license location. Within each family the four weight files are byte-identical variable-font downloads, consistent with the recorded identical URLs and the boundary's statement.
|
||||
- CSS uses the original family names; fonts are unmodified downloads kept with their notices, not relabeled under a code license. No license text was copied from v1; no trademark clearance is claimed anywhere.
|
||||
|
||||
## Claims versus evidence
|
||||
|
||||
Fresh independent reruns on the disposable copy (same Node 26.8.1, installed headless Chromium via CDP, fresh temporary profile) reproduce the author's receipts exactly:
|
||||
|
||||
- verify.mjs: 30 contrast sets / 840 pair checks, minimum normal-text ratio 4.503925718129755, 240 layouts, all interaction checks pass, no page errors.
|
||||
- detail-checks.mjs: 8,220 rendered-text samples across 30 combinations, minimum 4.504658476260286, zero failures; keyboard focus, accessible names, downloads, doubled text, blocked-fonts/denied-storage fallback all pass.
|
||||
- final-checks.mjs: local resources only, links/anchors resolve, breakpoints, 24 px targets, malformed-storage recovery all pass.
|
||||
- node --check passed on brand.js and board.js.
|
||||
- NOT RUN by reviewer (offline review): checks/references.mjs and checks/fetch-fonts.py, which deliberately use the network when run. Neither is invoked by the board.
|
||||
|
||||
## Draft-status preservation
|
||||
|
||||
- The board and notes consistently present the Assembly/DM Sans/Harbor recommendation as provisional ("My starting recommendation", "No logo is approved yet", "not cleared trademarks", "Not a working product", "The five dashboard designs have not been built").
|
||||
- DECISIONS.md preserves the chronology: intake answers, unapproved proposals, first owner feedback (Manrope/themes liked; logo association objection), and the gate revision. No first-feedback source change was implemented, matching the boundary.
|
||||
- Publication must carry the pending-owner-acceptance label (the author's suggested wording in the boundary declaration) at the publishing location. That label is the coordinator's to apply; no author source was edited for this review.
|
||||
|
||||
## Conditions of this approval
|
||||
|
||||
1. Publish only the exact 53-file candidate at the verified manifest; any change requires a new boundary and re-review.
|
||||
2. Apply the pending-owner-acceptance label; do not present the board's provisional recommendation as selected branding.
|
||||
3. Coordinator decides WUI-PUB-F1/F2 handling (keep as-is or addendum) before publication.
|
||||
|
||||
Evidence: `/tmp/filbert-wui-O0znVK/` (rerun logs verify-rerun.log, detail-rerun.log, final-rerun.log; regenerated reports in copy/evidence/). No git operations, live-seat mutation, source changes, or operator restart were performed.
|
||||
|
||||
## Correction, appended 2026-09-08 after coordinator disposition
|
||||
|
||||
The publication-safety section above says the author's and the coordinator's visual inspections stand behind the structural PNG checks. That was premature for the coordinator half: at verdict time only the author's inspection existed. The coordinator inspected all ten PNGs after receiving this verdict and recorded bounded visible-content findings (prototype and synthetic content only, ultrawide images viewed downscaled) in `docs/plans/reviews/2026-09-08_publication-trial-wui-condition-disposition.md`. This reviewer's visual NOT RUN limit stands unchanged. The approval's structural evidence and fresh reruns are unaffected.
|
||||
@@ -0,0 +1,53 @@
|
||||
c71e0c80c5976fbe5048624a7656ed9812164e3969f6ba76c43239e17746d20a agents/dewey/work/wui/BRIEF.md
|
||||
3c86ba0fd6aa894489caf83f6bff8fd94138c3ddd5f5b33858ef21426f8fce65 agents/dewey/work/wui/DECISIONS.md
|
||||
a7ad1f585702886de2d338f530ca5d29130c4acf8682c5d391f1b9e53bf86fe8 agents/dewey/work/wui/HISTORY.md
|
||||
e9cac40fe832d36429f02c4b0fa3e50cf63ccf3457b08e0326b8fc1b6c227b49 agents/dewey/work/wui/README.md
|
||||
fcc6d1ec1a35713f1bf765cbe83c9e526a4907d0cd2ce8889a2ef9ed6c54b25d agents/dewey/work/wui/RESEARCH.md
|
||||
04f2624b507109943d5e3ff5732c66d13816313e54a867ac1852341fb90cd309 agents/dewey/work/wui/TASKS.md
|
||||
63e96d72b6afd4eb8058c8b5b6846dbaa1c808dec1054ab23bfb3f5871f78801 agents/dewey/work/wui/VERIFY.md
|
||||
9fea608a947e67020c33cad9a6fe3d60c54119dfb8cff87768a8117a15ed7543 agents/dewey/work/wui/assets/fonts/dm-sans-400.woff2
|
||||
9fea608a947e67020c33cad9a6fe3d60c54119dfb8cff87768a8117a15ed7543 agents/dewey/work/wui/assets/fonts/dm-sans-500.woff2
|
||||
9fea608a947e67020c33cad9a6fe3d60c54119dfb8cff87768a8117a15ed7543 agents/dewey/work/wui/assets/fonts/dm-sans-600.woff2
|
||||
9fea608a947e67020c33cad9a6fe3d60c54119dfb8cff87768a8117a15ed7543 agents/dewey/work/wui/assets/fonts/dm-sans-700.woff2
|
||||
9af36190332437f5ecd09974de43c1f7c77a310a996cdd8ceb25628b458840e1 agents/dewey/work/wui/assets/fonts/dm-sans-OFL.txt
|
||||
89947da00bec2cbcacab815b7e36bf07a635dec41e3ca87a6eb2484a605a4e71 agents/dewey/work/wui/assets/fonts/dm-sans-sources.txt
|
||||
e2291e842cf5af167122a22881a740c7f2dda7716f1e8cd76680264f4a859470 agents/dewey/work/wui/assets/fonts/ibm-plex-sans-400.woff2
|
||||
e2291e842cf5af167122a22881a740c7f2dda7716f1e8cd76680264f4a859470 agents/dewey/work/wui/assets/fonts/ibm-plex-sans-500.woff2
|
||||
e2291e842cf5af167122a22881a740c7f2dda7716f1e8cd76680264f4a859470 agents/dewey/work/wui/assets/fonts/ibm-plex-sans-600.woff2
|
||||
e2291e842cf5af167122a22881a740c7f2dda7716f1e8cd76680264f4a859470 agents/dewey/work/wui/assets/fonts/ibm-plex-sans-700.woff2
|
||||
7e6b2818edbd8f6a01ae80641cc8f16a51080d08fb4e532be3a0b6f74adb07da agents/dewey/work/wui/assets/fonts/ibm-plex-sans-OFL.txt
|
||||
a762adc472b0911c4f5d0e3f0dd672c557c4b3debbc9b617488b46c36e10b183 agents/dewey/work/wui/assets/fonts/ibm-plex-sans-sources.txt
|
||||
a30ddcd349703aff7464c34bef3fffdff405ee50c113440d7c8693c02d210972 agents/dewey/work/wui/assets/fonts/manrope-400.woff2
|
||||
a30ddcd349703aff7464c34bef3fffdff405ee50c113440d7c8693c02d210972 agents/dewey/work/wui/assets/fonts/manrope-500.woff2
|
||||
a30ddcd349703aff7464c34bef3fffdff405ee50c113440d7c8693c02d210972 agents/dewey/work/wui/assets/fonts/manrope-600.woff2
|
||||
a30ddcd349703aff7464c34bef3fffdff405ee50c113440d7c8693c02d210972 agents/dewey/work/wui/assets/fonts/manrope-700.woff2
|
||||
e01b637272e0cbdfb240184dd98ea5cc671556d9894dae2668d92ab2c906787c agents/dewey/work/wui/assets/fonts/manrope-OFL.txt
|
||||
0d9aaaaa963b675d94d8fbee0cf47a8ecf03ea412f8b14aba96416375e5a2bb5 agents/dewey/work/wui/assets/fonts/manrope-sources.txt
|
||||
a1a047eb0b7f9c8f3e656d97d2292545371f8f0a92b4eb273cfd2fc371bd50ad agents/dewey/work/wui/assets/logos/aperture.svg
|
||||
d3d0eb03872b7336b00186beb95567840e5caf2bef29c2a9599480b29eb2f8da agents/dewey/work/wui/assets/logos/assembly.svg
|
||||
446cb7c0b75bb5cc7e3e08d9feb979c000531adfba0523aec81fb9af77f1ae55 agents/dewey/work/wui/assets/logos/relay.svg
|
||||
9efa30b490fa2cde89dcd3c9eafd37ae83a77a84a2a1965c78828e410be2b568 agents/dewey/work/wui/assets/palettes.json
|
||||
31222b6c40af7f253cceccc3d3caef5c2b0f9c0e096ea2eb5828b2224c3c47fe agents/dewey/work/wui/board.js
|
||||
d568df6dca14ae336db3b627639c8181c088649a21ffe992f9bfacc20b5b6238 agents/dewey/work/wui/brand.js
|
||||
e884333a3191921050c6ab45c7d87d40c6bc3092ba9d55c3c06bc5f0d01d5da3 agents/dewey/work/wui/checks/assets.mjs
|
||||
3ff14de07e87cc624433db6425b9d05e40d98f61e40f2bbf1fbee7431f9d73c1 agents/dewey/work/wui/checks/browser.mjs
|
||||
16b3cf3f7c8897dddef3b4caf1e9200272078cea8226a6df5e9ea1e7d25fe598 agents/dewey/work/wui/checks/detail-checks.mjs
|
||||
af924e53a19e3a639e5bc4c1e6a27253d03adcd935a8e1a847806761b797336c agents/dewey/work/wui/checks/fetch-fonts.py
|
||||
fd7d5baad1eb01c41ae98e1341aa5b16bb22e02f5296951381f48705b42d6855 agents/dewey/work/wui/checks/final-checks.mjs
|
||||
df79defbecf1500b6b5abdf7f0568c22ae88b437e841f0c95a7fa16d5d5fd3d2 agents/dewey/work/wui/checks/references.mjs
|
||||
bd6cc0c1021401207519e3489105284d120da2d8b85710e8fd51c1939f10e411 agents/dewey/work/wui/checks/verify.mjs
|
||||
41d4aababef4fdd5beff4f0b75fcdcd59e9a2fdf408a6a7aaf9f7afd86d1ac02 agents/dewey/work/wui/evidence/board-dark-1440.png
|
||||
9599769f4ed18363c3b7c0061823e0fd772d9cd516d3f72ab02e7b74a01de93c agents/dewey/work/wui/evidence/board-dim-1440.png
|
||||
d8097a2896c3c4348f709c1b25609207dad754d051994bc6f4835ed38d2cf290 agents/dewey/work/wui/evidence/board-light-1440.png
|
||||
8f5d62c30b8e6694e53608ba69c841024926c47d3934a76101a722856fa1e890 agents/dewey/work/wui/evidence/board-light-3440.png
|
||||
9e834a3f97bb446155d07f053adceaaeb1907d0397a44f5b31f8c7553d79931c agents/dewey/work/wui/evidence/board-light-390.png
|
||||
093e79080560bed7fdb0577298726613049830d1294f3515bc394dce7e62bcd2 agents/dewey/work/wui/evidence/detail-verification.json
|
||||
769e5e695ddec233323b59d226941edc6d98590b8e896588a92bf3366a2cee65 agents/dewey/work/wui/evidence/final-verification.json
|
||||
4b213ba93554d1651679d3d3189b6c25f799d2d6e88106ff09e109c0bf44685c agents/dewey/work/wui/evidence/section-color-ultrawide.png
|
||||
093f94495b5f4363a89ebb16228997e5c495f877f2ad4f621de2ec5e19acdaac agents/dewey/work/wui/evidence/section-components-mobile.png
|
||||
693de8c423cea8775810be8755ffe8a803215725bc8e9e1c9cb367bd905a1161 agents/dewey/work/wui/evidence/section-identity-light.png
|
||||
ffecc26d0f2e4f4a9c1d907160ca5a5ef9d85c4802c1aa5fd06304a02c7ea60e agents/dewey/work/wui/evidence/section-review-light.png
|
||||
379a5fea56a84bce71cd88995bae3011239f1990d51c5f5a270d7d47238b7ce3 agents/dewey/work/wui/evidence/section-typography-light.png
|
||||
73cd0e1795f2e81d1a5e6ae5068c5dea484dd37410ab233f6e30173a21c93cf7 agents/dewey/work/wui/evidence/verification.json
|
||||
ff0b6a8fd4e8cf5a0e8d3361243b730d83a86a8563562ffb62338b6635965235 agents/dewey/work/wui/index.html
|
||||
4f1309f4b4aec0d595300da060f49f7feb2b3042a8d73468894965ae83b9a04e agents/dewey/work/wui/styles.css
|
||||
@@ -5,7 +5,7 @@ REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "$REPO"
|
||||
|
||||
usage() {
|
||||
echo 'Usage: scripts/agent.sh --host-dev AGENT [--fresh] [--check] [--soul FILE] [--constitution FILE] [--user FILE]'
|
||||
echo 'Usage: scripts/agent.sh --host-dev AGENT [--fresh] [--check] [--soul FILE] [--constitution FILE] [--user FILE] [--provider NAME] [--model ID] [--thinking LEVEL]'
|
||||
echo 'Default: resume the latest agent development conversation; first launch starts one.'
|
||||
}
|
||||
fail() { echo "${AGENT:-tui}: $*" >&2; exit 1; }
|
||||
@@ -20,12 +20,23 @@ shift
|
||||
SOUL="$REPO/agents/$AGENT/SOUL.md"
|
||||
CONSTITUTION="$REPO/contracts/CONSTITUTION.md"
|
||||
USER_FILE=""
|
||||
PROVIDER=""
|
||||
MODEL=""
|
||||
THINKING=""
|
||||
FRESH=false
|
||||
CHECK=false
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
--fresh) FRESH=true; shift ;;
|
||||
--check) CHECK=true; shift ;;
|
||||
--provider|--model|--thinking)
|
||||
[ "$#" -ge 2 ] && [ -n "$2" ] && [[ "$2" != --* ]] || fail "$1 needs a value"
|
||||
case "$1" in
|
||||
--provider) PROVIDER="$2" ;;
|
||||
--model) MODEL="$2" ;;
|
||||
--thinking) THINKING="$2" ;;
|
||||
esac
|
||||
shift 2 ;;
|
||||
--soul|--constitution|--user)
|
||||
[ "$#" -ge 2 ] && [ -n "$2" ] || fail "$1 needs a file"
|
||||
case "$1" in
|
||||
@@ -43,6 +54,15 @@ done
|
||||
source "$REPO/scripts/common.sh"
|
||||
load_config
|
||||
[ "$MOSAIC_ADAPTER" = pi ] || fail 'native launcher requires the pi adapter'
|
||||
PROVIDER="${PROVIDER:-$MOSAIC_PROVIDER}"
|
||||
MODEL="${MODEL:-$MOSAIC_MODEL}"
|
||||
THINKING_ARGS=()
|
||||
if [ -n "$THINKING" ]; then
|
||||
case "$THINKING" in
|
||||
off|minimal|low|medium|high|xhigh|max) THINKING_ARGS=(--thinking "$THINKING") ;;
|
||||
*) fail "invalid thinking level: $THINKING" ;;
|
||||
esac
|
||||
fi
|
||||
USER_FILE="${USER_FILE:-$MOSAIC_DATA_ROOT/user/USER.md}"
|
||||
PI="$REPO/node_modules/.bin/pi"
|
||||
[ -x "$PI" ] || fail 'run npm ci --ignore-scripts --no-audit --no-fund in the repository first'
|
||||
@@ -62,7 +82,7 @@ for skill in "${SKILLS[@]}"; do
|
||||
done
|
||||
[ -s "$REPO/extensions/goal/index.ts" ] || fail 'missing canonical goal extension'
|
||||
STATE="$REPO/.pi/state/$AGENT"
|
||||
echo "$AGENT: native host TUI | Pi $PIN | $MOSAIC_PROVIDER/$MOSAIC_MODEL"
|
||||
echo "$AGENT: native host TUI | Pi $PIN | $PROVIDER/$MODEL${THINKING:+:$THINKING}"
|
||||
echo "$AGENT: workspace $REPO"
|
||||
echo "$AGENT: SOUL=$SOUL | CONSTITUTION=$CONSTITUTION | USER=$USER_FILE"
|
||||
echo "$AGENT: sessions $STATE/sessions | skills: ${SKILLS[*]}"
|
||||
@@ -116,5 +136,5 @@ exec "$PI" --approve --offline --no-context-files --no-extensions --no-skills \
|
||||
--extension "$REPO/.pi/extensions/goal/index.ts" \
|
||||
"${SKILL_ARGS[@]}" \
|
||||
--tools read,bash,edit,write,grep,find,ls,goal_report \
|
||||
--provider "$MOSAIC_PROVIDER" --model "$MOSAIC_MODEL" \
|
||||
--provider "$PROVIDER" --model "$MODEL" "${THINKING_ARGS[@]}" \
|
||||
--append-system-prompt "$PROMPT" "${SESSION_ARGS[@]}"
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
# [--session <name>] [--tools <comma,list>] [--auth <account>]
|
||||
# scripts/agent.sh --host-dev <name> [--fresh] [--check]
|
||||
# [--soul <file>] [--constitution <file>] [--user <file>]
|
||||
# [--provider <name>] [--model <id>] [--thinking <level>]
|
||||
#
|
||||
# The agent receives the four immutable contracts (constitution, standards,
|
||||
# SOUL, USER) plus its own identity and optional mission directives as its
|
||||
|
||||
@@ -7,13 +7,20 @@ import { join, resolve } from 'node:path';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
|
||||
const source = resolve(import.meta.dirname, '..');
|
||||
test('Darkwing launch context, resources, session recovery, and refusals', () => {
|
||||
const root = mkdtempSync(join(tmpdir(), 'darkwing launch '));
|
||||
for (const agent of ['darkwing', 'dewey', 'filbert']) test(`${agent} launch context, resources, session recovery, and refusals`, () => {
|
||||
const root = mkdtempSync(join(tmpdir(), `${agent} launch `));
|
||||
try {
|
||||
for (const dir of ['agents', 'scripts', 'contracts', 'user', 'node_modules/.bin', 'extensions/goal']) {
|
||||
mkdirSync(join(root, dir), { recursive: true });
|
||||
}
|
||||
cpSync(join(source, 'agents/darkwing'), join(root, 'agents/darkwing'), { recursive: true });
|
||||
// Copy only runtime inputs. Agent work/scratch may be large or actively
|
||||
// authored and is unrelated to isolated launcher verification.
|
||||
mkdirSync(join(root, `agents/${agent}`), { recursive: true });
|
||||
for (const file of ['launch.sh', 'SOUL.md', 'CONTEXT.md', 'validate-sessions.mjs']) {
|
||||
cpSync(join(source, `agents/${agent}`, file), join(root, `agents/${agent}`, file));
|
||||
}
|
||||
assert.equal(existsSync(join(root, `agents/${agent}/work`)), false);
|
||||
assert.equal(existsSync(join(root, `agents/${agent}/scratch`)), false);
|
||||
cpSync(join(source, 'scripts/agent-host-dev.sh'), join(root, 'scripts/agent-host-dev.sh'));
|
||||
cpSync(join(source, 'scripts/agent.sh'), join(root, 'scripts/agent.sh'));
|
||||
cpSync(join(source, 'skills'), join(root, 'skills'), { recursive: true });
|
||||
@@ -27,15 +34,15 @@ test('Darkwing launch context, resources, session recovery, and refusals', () =>
|
||||
writeFileSync(join(root, 'node_modules/.bin/pi'), `#!/usr/bin/env node
|
||||
const fs = require('node:fs');
|
||||
if (process.argv[2] === '--version') { console.log('0.84.4'); process.exit(0); }
|
||||
fs.writeFileSync('capture.json', JSON.stringify({args: process.argv.slice(2), incarnation: process.env.MOSAIC_LAUNCH_INCARNATION}));
|
||||
fs.writeFileSync('capture.json', JSON.stringify({args: process.argv.slice(2), agent: process.env.MOSAIC_AGENT_NAME, incarnation: process.env.MOSAIC_LAUNCH_INCARNATION}));
|
||||
`, { mode: 0o755 });
|
||||
const launch = (args = '', tty = true) => spawnSync(tty ? 'script' : 'bash', tty
|
||||
? ['-q', '-e', '-c', `bash agents/darkwing/launch.sh ${args}`, '/dev/null']
|
||||
: ['agents/darkwing/launch.sh', ...args.split(' ').filter(Boolean)],
|
||||
? ['-q', '-e', '-c', `bash agents/${agent}/launch.sh ${args}`, '/dev/null']
|
||||
: [`agents/${agent}/launch.sh`, ...args.split(' ').filter(Boolean)],
|
||||
{ cwd: root, env: { ...process.env, MOSAIC_LAUNCH_INCARNATION: 'must-not-inherit' }, encoding: 'utf8', timeout: 10000 });
|
||||
const ok = (result) => assert.equal(result.status, 0, result.stdout + result.stderr);
|
||||
ok(launch('--check', false));
|
||||
const direct = spawnSync('bash', [join(root, 'scripts/agent.sh'), '--host-dev', 'darkwing', '--check'],
|
||||
const direct = spawnSync('bash', [join(root, 'scripts/agent.sh'), '--host-dev', agent, '--check'],
|
||||
{ cwd: tmpdir(), encoding: 'utf8', timeout: 10000 });
|
||||
ok(direct);
|
||||
assert.match(direct.stdout, /configuration checks passed/);
|
||||
@@ -44,6 +51,11 @@ fs.writeFileSync('capture.json', JSON.stringify({args: process.argv.slice(2), in
|
||||
ok(launch());
|
||||
let captured = JSON.parse(readFileSync(join(root, 'capture.json')));
|
||||
assert.equal(captured.incarnation, undefined);
|
||||
assert.equal(captured.agent, agent);
|
||||
assert.equal(captured.args[captured.args.indexOf('--provider') + 1], agent === 'filbert' ? 'openai-codex' : 'test');
|
||||
assert.equal(captured.args[captured.args.indexOf('--model') + 1], agent === 'filbert' ? 'gpt-6-astra' : 'test-model');
|
||||
if (agent === 'filbert') assert.equal(captured.args[captured.args.indexOf('--thinking') + 1], 'low');
|
||||
assert.equal(captured.args[captured.args.indexOf('--session-dir') + 1], join(root, `.pi/state/${agent}/sessions`));
|
||||
assert.equal(captured.args.includes('--continue'), false);
|
||||
assert.ok(captured.args.includes('--no-context-files'));
|
||||
assert.ok(captured.args.includes('--no-skills'));
|
||||
@@ -54,8 +66,8 @@ fs.writeFileSync('capture.json', JSON.stringify({args: process.argv.slice(2), in
|
||||
assert.match(context, /fixture contracts\/CONSTITUTION.md/);
|
||||
assert.match(context, /fixture user\/USER.md/);
|
||||
assert.match(context, /fixture AGENTS.md/);
|
||||
assert.match(context, /You are Darkwing/);
|
||||
const sessions = join(root, '.pi/state/darkwing/sessions');
|
||||
assert.match(context, new RegExp(`You are ${agent[0].toUpperCase() + agent.slice(1)}`));
|
||||
const sessions = join(root, `.pi/state/${agent}/sessions`);
|
||||
const session = join(sessions, 'history.jsonl');
|
||||
const history = JSON.stringify({ type: 'session', version: 3, id: 'test', cwd: root, timestamp: new Date().toISOString() }) + '\n';
|
||||
writeFileSync(session, history);
|
||||
@@ -73,10 +85,10 @@ fs.writeFileSync('capture.json', JSON.stringify({args: process.argv.slice(2), in
|
||||
assert.notEqual(launch('--unexpected', false).status, 0);
|
||||
assert.notEqual(launch('', false).status, 0);
|
||||
const locked = spawnSync('script', ['-q', '-e', '-c',
|
||||
'flock .pi/state/darkwing/launch.lock bash agents/darkwing/launch.sh --fresh', '/dev/null'],
|
||||
`flock .pi/state/${agent}/launch.lock bash agents/${agent}/launch.sh --fresh`, '/dev/null'],
|
||||
{ cwd: root, encoding: 'utf8', timeout: 10000 });
|
||||
assert.notEqual(locked.status, 0);
|
||||
assert.match(locked.stdout, /another darkwing TUI/);
|
||||
assert.match(locked.stdout, new RegExp(`another ${agent} TUI`));
|
||||
writeFileSync(join(root, 'alternate.md'), 'alternate user context\n');
|
||||
ok(launch('--fresh --user alternate.md'));
|
||||
captured = JSON.parse(readFileSync(join(root, 'capture.json')));
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
// Offline Claude launcher checks; no authentication or model calls.
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { mkdtempSync, mkdirSync, writeFileSync, readFileSync, cpSync, existsSync, rmSync } from 'node:fs';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { join, resolve } from 'node:path';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
|
||||
const source = resolve(import.meta.dirname, '..');
|
||||
test('Rocko uses Sonnet, isolated resume IDs, current context and launch refusals', () => {
|
||||
const root = mkdtempSync(join(tmpdir(), 'rocko launch '));
|
||||
try {
|
||||
for (const dir of ['agents', 'scripts', 'contracts', 'user', 'bin']) mkdirSync(join(root, dir), { recursive: true });
|
||||
cpSync(join(source, 'agents/rocko'), join(root, 'agents/rocko'), { recursive: true });
|
||||
for (const file of ['contracts/CONSTITUTION.md', 'contracts/STANDARDS.md', 'user/USER.md', 'AGENTS.md']) {
|
||||
writeFileSync(join(root, file), `fixture ${file}\n`);
|
||||
}
|
||||
writeFileSync(join(root, 'scripts/common.sh'), 'load_config() { MOSAIC_DATA_ROOT="$PWD"; }\n');
|
||||
writeFileSync(join(root, 'bin/claude'), `#!/usr/bin/env node
|
||||
const fs = require('node:fs');
|
||||
if (process.argv[2] === '--version') { console.log('fixture Claude'); process.exit(0); }
|
||||
fs.writeFileSync('capture.json', JSON.stringify({args: process.argv.slice(2), cwd: process.cwd(), agent: process.env.MOSAIC_AGENT_NAME, incarnation: process.env.MOSAIC_LAUNCH_INCARNATION}));
|
||||
if (process.env.FAKE_CLAUDE_FAIL) process.exit(7);
|
||||
`, { mode: 0o755 });
|
||||
const env = { ...process.env, PATH: `${join(root, 'bin')}:${process.env.PATH}`, MOSAIC_LAUNCH_INCARNATION: 'do-not-inherit' };
|
||||
const run = (args = '', tty = true, extraEnv = {}) => spawnSync(tty ? 'script' : 'bash', tty
|
||||
? ['-q', '-e', '-c', `bash agents/rocko/launch.sh ${args}`, '/dev/null']
|
||||
: [join(root, 'agents/rocko/launch.sh'), ...args.split(' ').filter(Boolean)],
|
||||
{ cwd: tty ? root : tmpdir(), env: { ...env, ...extraEnv }, encoding: 'utf8', timeout: 10000 });
|
||||
const ok = result => assert.equal(result.status, 0, result.stdout + result.stderr);
|
||||
const capture = () => JSON.parse(readFileSync(join(root, 'capture.json')));
|
||||
const state = join(root, '.pi/state/rocko');
|
||||
ok(run('--check', false));
|
||||
assert.equal(existsSync(state), false);
|
||||
assert.equal(existsSync(join(root, 'capture.json')), false);
|
||||
ok(run());
|
||||
let captured = capture();
|
||||
assert.equal(captured.cwd, root);
|
||||
assert.equal(captured.agent, 'rocko');
|
||||
assert.equal(captured.incarnation, undefined);
|
||||
assert.equal(captured.args[captured.args.indexOf('--model') + 1], 'sonnet');
|
||||
assert.equal(captured.args[captured.args.indexOf('--name') + 1], 'Rocko');
|
||||
assert.equal(captured.args.includes('--continue'), false);
|
||||
assert.equal(captured.args.includes('--dangerously-skip-permissions'), false);
|
||||
assert.equal(captured.args.includes('--agent'), false);
|
||||
const firstId = readFileSync(join(state, 'session-id'), 'utf8').trim();
|
||||
assert.equal(captured.args[captured.args.indexOf('--session-id') + 1], firstId);
|
||||
const prompt = captured.args[captured.args.indexOf('--append-system-prompt') + 1];
|
||||
for (const value of ['You are Rocko', 'Darkwing', 'fixture AGENTS.md', 'fixture user/USER.md', 'ROCKO NATIVE DEVELOPMENT CONTEXT']) assert.ok(prompt.includes(value));
|
||||
writeFileSync(join(root, 'agents/rocko/SOUL.md'), 'You are Rocko. Updated context.\n');
|
||||
ok(run());
|
||||
captured = capture();
|
||||
assert.equal(captured.args[captured.args.indexOf('--resume') + 1], firstId);
|
||||
assert.equal(captured.args.includes('--session-id'), false);
|
||||
assert.match(captured.args[captured.args.indexOf('--append-system-prompt') + 1], /Updated context/);
|
||||
const failed = run('', true, { FAKE_CLAUDE_FAIL: '1' });
|
||||
assert.equal(failed.status, 7);
|
||||
assert.equal(readFileSync(join(state, 'session-id'), 'utf8').trim(), firstId);
|
||||
ok(run('--fresh'));
|
||||
const secondId = readFileSync(join(state, 'session-id'), 'utf8').trim();
|
||||
assert.notEqual(secondId, firstId);
|
||||
assert.equal(capture().args.includes('--resume'), false);
|
||||
writeFileSync(join(state, 'session-id'), 'corrupt\n');
|
||||
assert.notEqual(run().status, 0);
|
||||
ok(run('--fresh'));
|
||||
assert.notEqual(run('--unexpected', false).status, 0);
|
||||
assert.notEqual(run('--user missing.md --check', false).status, 0);
|
||||
assert.notEqual(run('', false).status, 0);
|
||||
const locked = spawnSync('script', ['-q', '-e', '-c',
|
||||
'flock .pi/state/rocko/launch.lock bash agents/rocko/launch.sh --fresh', '/dev/null'],
|
||||
{ cwd: root, env, encoding: 'utf8', timeout: 10000 });
|
||||
assert.notEqual(locked.status, 0);
|
||||
assert.match(locked.stdout, /another rocko TUI/);
|
||||
writeFileSync(join(root, 'alternate.md'), 'alternate user context\n');
|
||||
ok(run('--fresh --user alternate.md'));
|
||||
captured = capture();
|
||||
assert.match(captured.args[captured.args.indexOf('--append-system-prompt') + 1], /alternate user context/);
|
||||
} finally {
|
||||
rmSync(root, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||