* feat(sessions): stamp agent identity on spawned sessions and return spawn receipts Agent-spawned sessions recorded the requesting session key as createdActor.id, so the Control UI creator chip rendered an opaque key. Spawn producers now stamp the canonical requester agent id; parent-authority validation moves to a new trusted requesterSessionKey field. projectSessionActor enriches agent actors with configured identity name/avatar at read time, and visible sessions_spawn returns a sessionUrl + owner receipt with URL-first acknowledgement guidance. * feat(sessions): assignable session ownership with owner facet and menus GitHub-assignee-style ownership: sessions get a mutable owner (defaulting to the immutable createdActor) stored in additive bare-nullable SQLite columns with first-use lazy ensure. New operator.write sessions.assignOwner validates targets, requires an identified caller, authorizes by session visibility, and records assignedBy/assignedAt inside the write transaction. The sessions agent tool gains assign_owner; the Control UI adds Assign-to-me/Assign-to menus in sidebar rows and chat headers, renders the effective owner chip, and the creator facet/filter now keys on effective owner. Sharing authority stays anchored on createdActor. * feat(sessions): record session participants and stack them in the owner chip Records every distinct external prompter (human profile/channel sender, or a requesting agent) per session in an additive session_participants table at the turn-admission boundary — best-effort, deferred, never blocking the turn; the session's own agent and viewers are never recorded, capped at 32 per session. The session row projects a bounded participants list (owner excluded) plus a total count with the same actor enrichment as owner/createdActor. The sidebar chip becomes a pair-stack when others have prompted (owner front, one peeking participant or +N behind), the chat header shows the full facepile, and an authenticated involvingMe list filter adds an Involving-me sidebar predicate. Participant projection is excluded from logical-session CAS equality so display history never invalidates session writes. * fix(sessions): identify built-in agent tool callers for owner assignment The sessions tool's assign_owner dispatched through the in-process synthetic client, which carries neither a signed agent-runtime identity nor a human profile, so agent-initiated reassignment always failed with FORBIDDEN. The tool now captures its trusted requester agent identity and carries it across in-process dispatch as internal client state (never wire params); the handler derives assignedBy as signed runtime identity, then trusted agent-tool caller, then authenticated human. Live-verified end-to-end on a dev gateway. * fix(ci): split oversized session modules and refresh prompt snapshots Split the max-lines offenders at concept boundaries for session equality, tool overrides, and protocol owner schemas. Remove the redundant Number conversion from the node:sqlite participant count. Refresh prompt snapshots after drift from the sessions and sessions_spawn tool description updates. * fix(ci): restore solo-mode chip suppression and conform new method descriptors Solo-mode root cause: owner-assignment submenu options reused the permanent owner-chip custom element, so hidden menu avatars were counted as attribution chrome. Menus now use viewer avatars while gateway-gated owner chips remain exclusive to collaborative sessions. Conform sessions.assignOwner to the 2026.8 descriptor and append-only advertised-method inventories, and regenerate the Swift and Kotlin protocol surfaces. Keep historical v15/v14 fixtures frozen by stripping the new owner columns; the existing range already excludes the participant table. Replace the new raw SQLite schema probes with synchronous Kysely queries. Clear max-lines by splitting the organizer host contract, pure agent-navigation projections, and ownership/filtering sidebar cases at their concept boundaries. * fix(ci): integrate ownership series with latest main surfaces Wire the sessions-page assign-owner action, merge capability imports, narrow the navigation export scope, and apply sessions-create formatting. The owner-presence regression came from hidden assign-owner menu avatars emitting data-viewer-id, so owner and menu chrome now opt out of presence markers while real facepiles retain them. * fix(sessions): scope the involving-me filter to profile-backed participants Session participant history mixed channel-native sender ids with authenticated Gateway profile ids, so involving-me missed real sessions and could accept numeric collisions. Record the actor_source namespace at each producer, carry it through the internal SQLite projection, and match authenticated viewers only against profile-backed human participants. Legacy NULL sources fail closed for filtering, while channel ids remain available for display. * build(ui): raise startup budget baseline for session ownership surfaces Ownership chips, assignment menus, and the participant stack add ~0.7 KiB gzip to the startup path; CI compression landed just over the previous baseline+tolerance. Hard cap (350 KiB) unchanged. * refactor(sessions): drop raw NULL projection for the lazy actor_source column The Kysely guardrail rejects typed raw sql snippets outside allowlisted boundaries; select the lazily-ensured column only when present and let the row projection treat its absence as unknown/legacy. * build(ui): refresh combined startup baseline
summary, read_when, title
| summary | read_when | title | |||
|---|---|---|---|---|---|
| Repository script entry points and compatibility notes |
|
Scripts Directory |
Scripts Directory
The scripts/ directory contains repository tooling used by local development,
CI, docs publishing, releases, Docker proof, and maintainer operations. Prefer
the package-script entry points in package.json when one exists, then read the
underlying script before running it directly.
Compatibility
Many scripts are stable paths referenced by package.json, GitHub Actions,
docs, and maintainer runbooks. Do not move, rename, or regroup scripts only to
improve taxonomy. A directory migration needs an explicit maintainer-approved
compatibility plan for package scripts, workflows, docs snippets, and any raw
script paths users may have copied.
This index is a discovery aid for the current flat layout. It does not define a new directory taxonomy.
Common Entry Points
| Area | Prefer | Notes |
|---|---|---|
| Build | pnpm build |
Runs scripts/build-all.mts; use specific build scripts only when debugging a build stage. |
| Changed checks | pnpm changed:lanes --json, pnpm check:changed |
Lane classification lives in scripts/changed-lanes.mjs; changed-file checks live in scripts/check-changed.mjs. |
| Docs | pnpm docs:list, pnpm docs:check-mdx, pnpm docs:check-links |
Backed by scripts/docs-list.js, scripts/check-docs-mdx.mjs, and scripts/docs-link-audit.mjs. |
| Formatting docs | pnpm format:docs:check |
Uses scripts/format-docs.mts; use write mode only when intentionally formatting docs. |
| Lint | pnpm lint, pnpm lint:core, pnpm lint:all |
Wrapper scripts keep oxlint behavior aligned with repo config. |
| Targeted tests | pnpm test <path-or-filter> or node scripts/run-vitest.mjs <path-or-filter> |
Avoid bare vitest; it can start watch mode. |
| Changed tests | pnpm test:changed |
Uses the repo's changed-test resolver instead of a broad Vitest run. |
| Docker proof | pnpm test:docker:all, pnpm test:docker:rerun, pnpm test:docker:timings |
Use the planner/rerun helpers before launching broad Docker work. |
| Live proof | pnpm test:live |
Live checks require the matching environment and credentials. |
| Release checks | pnpm release:check, pnpm release:beta, pnpm release:candidate |
Release scripts are maintainer workflows; read release docs before use. |
| GitHub reads | scripts/gh-read |
Uses a GitHub App read token when configured, leaving normal gh login for writes. |
| Commits | git add <files...> then git commit -m "<message>" |
Stage only the intended files for each commit. |
| Remote proof | node scripts/crabbox-wrapper.mjs ... |
Use when the current host lacks the required isolation, OS, device, or capacity; sync each run and reuse the lease. |
Script Families
check-*.mts/check-*.ts/ retainedcheck-*.mjs: guardrails for architecture, docs, package contents, boundaries, workflows, and generated artifacts.run-*.mjs/run-*.mts: stable wrappers and typed implementations for Node, Vitest, oxlint, tsgo, and environment setup.test-*.mts/ retainedtest-*.mjs/test-*.sh/test-*.ts: test planners, Docker lanes, live checks, and focused validation helpers.docs-*andcheck-docs-*: docs listing, link auditing, MDX checks, spellcheck, sync, and i18n glossary checks.release-*,openclaw-npm-*, andplugin-*-release-*: release preparation, package verification, and publishing helpers.docker-*,test-docker-*, andtest-live-*-docker.sh: Docker E2E planning, rerun, timing, and live/package lane helpers.gh-read*,label-*,sync-labels.ts, and PR helpers: GitHub read, labeling, and maintainer workflow support.generate-*,write-*,copy-*, andsync-*: generated docs, metadata, package surfaces, and build artifact support.lib/: shared helpers imported by script entry points.
Maintenance Rules
- Read
scripts/AGENTS.mdbefore changing scripts. - Keep package scripts, generators, generated-artifact checks, docs references, and workflow references aligned when touching a script path.
- Prefer existing wrappers instead of introducing a raw tool invocation.
- Add or update focused tests under
test/scripts/when changing script behavior.
See also Scripts for public-facing script guidance.