源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,529 @@
|
||||
# Project Structure
|
||||
|
||||
This document defines the current repository structure for `tutti`.
|
||||
|
||||
It explains what belongs in each top-level area and how new directories should be introduced.
|
||||
|
||||
## Top-Level Layout
|
||||
|
||||
```text
|
||||
tutti/
|
||||
apps/
|
||||
config/
|
||||
services/
|
||||
packages/
|
||||
tools/
|
||||
docs/
|
||||
```
|
||||
|
||||
## Top-Level Responsibilities
|
||||
|
||||
### `apps/`
|
||||
|
||||
`apps/` contains product entrypoints and user-facing shells.
|
||||
|
||||
Current area:
|
||||
|
||||
- `apps/cli`: bundled terminal entrypoint for the local daemon capability protocol
|
||||
- `apps/desktop`: Electron desktop application
|
||||
|
||||
Rules:
|
||||
|
||||
- app directories may own presentation, runtime integration, and entrypoint-specific behavior
|
||||
- app directories must not duplicate business logic already owned by `services/`
|
||||
- do not materialize future app ideas as empty directories; keep them in docs until the module has a real interface and implementation
|
||||
|
||||
### `services/`
|
||||
|
||||
`services/` contains long-running product backends.
|
||||
|
||||
Current area:
|
||||
|
||||
- `services/tuttid`: local daemon and primary business core
|
||||
|
||||
Rules:
|
||||
|
||||
- service directories own business workflows, durable state, and persistence ownership
|
||||
- if a feature requires domain decisions or state transitions, it should usually land in `services/tuttid`
|
||||
|
||||
### `config/`
|
||||
|
||||
`config/` contains repository-owned default sources that are consumed by generation or tooling.
|
||||
|
||||
Current area:
|
||||
|
||||
- `config/tutti.defaults.json`: single-source default names and budgets for local state, transport, and logging
|
||||
|
||||
Rules:
|
||||
|
||||
- keep `config/` focused on repository defaults, not per-user settings or secrets
|
||||
- prefer generating runtime-specific code from `config/` rather than reading these files ad hoc inside packaged applications
|
||||
- do not turn `config/` into a second `docs/` directory; only keep machine-consumable sources here
|
||||
|
||||
### `packages/`
|
||||
|
||||
`packages/` contains shared boundaries, not default implementation code.
|
||||
|
||||
Current grouping:
|
||||
|
||||
```text
|
||||
packages/
|
||||
browser/
|
||||
clients/
|
||||
configs/
|
||||
connector/
|
||||
device-link/
|
||||
events/
|
||||
ui/
|
||||
workbench/
|
||||
workspace/
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
- organize packages by responsibility, not by language alone
|
||||
- use `clients/*` for domain-specific client access
|
||||
- use `device-link` for shared ICE/QUIC peer transport, product-neutral Relay stream mechanics, and the gomobile boundary consumed by Tutti, TSH, and mobile clients
|
||||
- use `events/*` for schema-first shared business event protocol contracts, validators, and generated transport metadata that multiple hosts consume
|
||||
- use `browser/*` for reusable browser/workbench node mechanics that are shared by desktop hosts without carrying product-specific bridge methods
|
||||
- use `configs/*` for shared engineering configuration
|
||||
- use `ui/*` for shared frontend foundation packages such as visual-system boundaries, host-agnostic React hooks, and host-agnostic i18n runtime support
|
||||
- use `workbench/*` for the shared workbench snapshot contract and reusable workbench interaction surface intended to be shared by the open-source desktop and TSH
|
||||
- use `workspace/*` for narrow reusable workspace-domain contracts and feature surfaces intended to be shared by the open-source desktop, TSH, and TACH
|
||||
- do not create vague packages such as `shared`, `common`, or `client-sdk`
|
||||
- do not pre-create package directories for future domains; add the package only when a real multi-consumer seam exists
|
||||
- documentation alone does not make a package seam real; the package must expose
|
||||
a narrow interface that a current consumer can use without learning its
|
||||
implementation layout
|
||||
|
||||
### `tools/`
|
||||
|
||||
`tools/` contains repository support code such as:
|
||||
|
||||
- build helpers
|
||||
- packaging helpers
|
||||
- generation entrypoints
|
||||
- validation or maintenance scripts
|
||||
|
||||
Core product behavior should not permanently live in ad hoc scripts when it belongs in a first-class application or service.
|
||||
|
||||
### `docs/`
|
||||
|
||||
`docs/` contains persistent repository documentation.
|
||||
|
||||
Current sub-areas:
|
||||
|
||||
- `docs/architecture`: structure notes and technical design context
|
||||
- `docs/conventions`: coding, layering, naming, and storage rules
|
||||
|
||||
Rules:
|
||||
|
||||
- `docs/architecture` and `docs/conventions` are the long-lived source of truth
|
||||
- temporary planning notes should not become the primary source of current repository rules
|
||||
- once a design has landed and stabilized, durable rules should be promoted into `docs/architecture` or `docs/conventions`
|
||||
|
||||
## Current Structure Decisions
|
||||
|
||||
### `apps/cli`
|
||||
|
||||
`apps/cli` is responsible for:
|
||||
|
||||
- terminal argument parsing
|
||||
- local daemon endpoint discovery and bearer authentication
|
||||
- invoking the daemon-owned CLI capability protocol
|
||||
- rendering daemon command output for terminal users
|
||||
|
||||
It must not become a second business core. Command metadata, workspace resolution, edition/context filtering, and command execution stay in `services/tuttid`.
|
||||
|
||||
### `apps/desktop`
|
||||
|
||||
`apps/desktop` is responsible for:
|
||||
|
||||
- renderer UI
|
||||
- Electron main-process lifecycle
|
||||
- preload bridge and IPC exposure
|
||||
- native desktop integration
|
||||
- supervising `tuttid`
|
||||
|
||||
It must not become a second business core.
|
||||
|
||||
Desktop keeps four top-level source areas:
|
||||
|
||||
```text
|
||||
apps/desktop/src/
|
||||
main/
|
||||
preload/
|
||||
renderer/
|
||||
shared/
|
||||
```
|
||||
|
||||
Desktop summary:
|
||||
|
||||
- `main/` owns Electron lifecycle, daemon/runtime composition, host access, transport, IPC, update integration, and window creation
|
||||
- `preload/` owns the typed bridge surface exposed to renderer
|
||||
- `renderer/src/app/windows/*` owns renderer window composition shells such as `dashboard` and `workspace`
|
||||
- `renderer/src/features/*` owns reusable renderer feature modules
|
||||
- `renderer/src/features/*/services/*` owns feature service public surfaces, while `services/internal/**` stays private to the owning feature
|
||||
- `renderer` consumes shared visual foundations from `packages/ui/system` instead of growing its own token or primitive layer
|
||||
- `shared/` stays narrow and desktop-local
|
||||
- desktop-owned i18n resources stay under `shared/i18n/*`, while reusable package default i18n resources stay with the owning package and are merged by the renderer app-level i18n runtime
|
||||
- `main/bootstrap.ts` stays a top-level coordinator; service assembly belongs in `desktopAppServices.ts`, `desktopDaemonRuntime.ts`, `desktopHostServices.ts`, and `desktopAppLifecycle.ts`
|
||||
|
||||
The authoritative desktop directory shape and ownership rules live in [docs/conventions/desktop-layering.md](../conventions/desktop-layering.md). Keep this repository-level document as a summary, not a second full desktop structure spec.
|
||||
|
||||
### `packages/desktop/*`
|
||||
|
||||
Desktop packages own product-neutral lifecycle and native-host integration
|
||||
mechanics shared by more than one desktop product.
|
||||
|
||||
Current packages:
|
||||
|
||||
- `packages/desktop/update-admission`: minimum-version policy contracts,
|
||||
validation, mandatory updater ownership, Electron admission lifecycle,
|
||||
capability-minimal preload API, shared React presentation, and default i18n
|
||||
|
||||
Product policy transport, normal update preferences, release feeds, download
|
||||
URLs, window assets, logging sinks, and business-window enumeration remain in
|
||||
the consuming desktop app.
|
||||
|
||||
### `packages/connector/*`
|
||||
|
||||
Connector packages own host-neutral connector domain boundaries shared across
|
||||
desktop daemons.
|
||||
|
||||
Current owners:
|
||||
|
||||
- `packages/connector/contracts`: versioned authorization wire contracts and
|
||||
the local OpenAPI fragment
|
||||
- `packages/connector/daemon/core`: connector catalog, installation, authorization,
|
||||
compatibility, operation, and recovery application core
|
||||
- `packages/connector/daemon/application`: reusable daemon lifecycle and workers
|
||||
- `packages/connector/daemon/adapters/sqlite`: canonical local persistence and outbox
|
||||
- `packages/connector/daemon/adapters/controlplane`: account-scoped authorization
|
||||
HTTP and realtime protocol adapter
|
||||
- `packages/connector/runtime`: latest-only artifact caching, no-network archive
|
||||
import, same-machine composition, managed-runtime installation primitives,
|
||||
Connector route/MCP registries, and the session-bound loopback MCP server
|
||||
- `packages/connector/renderer`: React-free frontend application services plus
|
||||
the only shared Connector-specific React and i18n owner
|
||||
|
||||
Remote endpoint authentication, credentials, state-root selection, generated
|
||||
daemon clients, product command publication, and OS process integration remain
|
||||
in host adapters.
|
||||
|
||||
### `services/tuttid`
|
||||
|
||||
`services/tuttid` is the primary business core.
|
||||
|
||||
It owns:
|
||||
|
||||
- business rules
|
||||
- domain workflows
|
||||
- local persistence
|
||||
- long-running daemon behavior
|
||||
|
||||
### `packages/clients/*`
|
||||
|
||||
Client packages provide domain-specific access helpers for consumers.
|
||||
|
||||
They should remain focused, named by responsibility, and free of hidden business rules.
|
||||
|
||||
`packages/connector/daemon/adapters/controlplane` is the shared Go protocol client for
|
||||
account-scoped Connector authorization. It owns authorization session,
|
||||
snapshot, and realtime-event decoding plus bounded HTTPS transport. A product
|
||||
host supplies the API prefix, HTTP client, and per-account request authorizer;
|
||||
the package never stores account cookies, chooses an environment, or sends
|
||||
credentials to a runtime VM. `packages/connector/daemon/core` selects this client only
|
||||
for `remote_streamable_http` releases, while `managed_stdio` authorization
|
||||
stays with the injected local implementation host.
|
||||
|
||||
`packages/clients/device-authority-go` is the shared Go client boundary for the
|
||||
Device Authority owner lifecycle across Tutti and TSH. The initial package is a
|
||||
staged cross-repository extraction from TSH: publish the stable module first,
|
||||
then refactor TSH to the released version without changing behavior, then wire
|
||||
the same client into Tutti. This ordering is required because cross-repository
|
||||
consumers must not use workspace replacements or pseudo-versions. The package
|
||||
owns the control-plane wire contract, canonical Ed25519 enrollment and
|
||||
owner-token signing, bounded HTTP response semantics, and credential-binding
|
||||
validation. Product adapters still own base-URL and API-prefix selection,
|
||||
account/session/device headers, durable identity storage, Relay demand and lease
|
||||
scheduling, logging, and retry policy. The client must not infer
|
||||
local-versus-remote deployment policy or import Relay transport lifecycle code.
|
||||
|
||||
`packages/clients/market-go` is the market-neutral generated Go client boundary
|
||||
for TSH Market. It pins the provider-generated protobuf and HTTP artifacts to an
|
||||
exact `tsh-server` commit and SHA-256 values without importing the server
|
||||
application module or copying the remote schema into Tutti's local OpenAPI.
|
||||
The update tool verifies the source checkout commit before copying digest-matched
|
||||
files. Product adapters inject the HTTP transport, gateway base path, and request
|
||||
authorization. Connector consumers pass `itemType=connector`; future Skill
|
||||
consumers reuse the same client with `itemType=skill`.
|
||||
|
||||
### `packages/device-link`
|
||||
|
||||
DeviceLink is the shared Go peer-transport boundary for Tutti Desktop, TSH
|
||||
Desktop, and mobile clients. It owns ICE candidate negotiation, QUIC over the
|
||||
selected packet path, mutual ephemeral certificate pinning, categorical path
|
||||
classification, the gomobile build surface, and product-neutral authenticated
|
||||
link lifecycle mechanics: generation-fenced admission, establishment
|
||||
serialization, pooled stream ownership, connection racing, and annealed path
|
||||
probing. It also owns generic Relay byte-stream dialing and the reusable
|
||||
reference-counted WebSocket/yamux owner-tunnel mechanics, including liveness,
|
||||
readiness ordering, reconnect backoff, stream dispatch, and close ordering.
|
||||
|
||||
Its `candidateexchange` subpackage also owns the Trickle ICE application
|
||||
mechanics shared by Go and gomobile consumers: immediate credential snapshots,
|
||||
candidate change coalescing, acknowledgement-bound exact-snapshot publication
|
||||
retry, gathering completion, and push-hint plus authoritative-poll remote
|
||||
refresh. Consumers provide rendezvous callbacks or execute facade actions and
|
||||
retain product retry classification; account authorization, attempt state,
|
||||
request signing, room/pairing semantics, and wire DTOs stay in their product
|
||||
adapter. The callback-free Go `ActionPump` owns both candidate workers and
|
||||
allows at most one unresolved action per worker, so a slow rendezvous read does
|
||||
not block local publication. The gomobile facade exports scalar/JSON start,
|
||||
next-action, resolve-action, notify, and stop/cancel operations. Mobile uses two
|
||||
identical action drainers to execute signed authoritative reads/writes without
|
||||
reimplementing ICE retry timing, wake cursors, polling, or worker cancellation
|
||||
in TypeScript, Kotlin, or Objective-C.
|
||||
|
||||
It exposes authenticated bidirectional streams and generic Relay byte streams,
|
||||
and must remain independent of Agent, Session, Workspace, account, pairing,
|
||||
rendezvous, Relay authorization, and Relay product policy. Peer and owner keys
|
||||
stay opaque; host services and apps inject path dialers, credentials, leases,
|
||||
fallback timing, and application stream protocols. The `tuttid` Mobile Remote
|
||||
owner is the first adapter for the shared link manager; its pairing and Agent
|
||||
framing remain service-owned. TSH remains the product authority for its Relay
|
||||
registration and lease lifecycle even when it consumes the shared owner-tunnel
|
||||
mechanics. Raw addresses, candidates, credentials, and payloads must not enter
|
||||
ordinary logs or metrics.
|
||||
|
||||
### `packages/events/*`
|
||||
|
||||
Event packages define shared business event protocol boundaries.
|
||||
|
||||
Current package:
|
||||
|
||||
- `packages/events/protocol`: repository-owned JSON Schema and event-definition source files for the business event stream, plus generated TypeScript protocol contracts and daemon transport registry output
|
||||
|
||||
Rules:
|
||||
|
||||
- keep schema-first source files in the package and keep those files as the only shared source of truth for business event topics
|
||||
- keep generated TypeScript exports narrow and protocol-oriented
|
||||
- keep WebSocket lifecycle management, daemon orchestration, and renderer feature behavior outside `events/*`
|
||||
|
||||
### `packages/browser/*`
|
||||
|
||||
Browser packages define reusable Browser Node mechanics for hosts that need to
|
||||
embed web content in the shared Workbench.
|
||||
|
||||
Current packages:
|
||||
|
||||
- `packages/browser/workbench-node`: `@tutti-os/browser-node`, the shared
|
||||
Workbench Browser Node package. It owns generic HTTP/HTTPS navigation,
|
||||
session partition resolution, runtime state, bridge shape, Electron webview
|
||||
guest management, and package-local i18n defaults. Host adapters own product
|
||||
globals, backend-token access, preview proxy behavior, and business bridge
|
||||
methods.
|
||||
|
||||
Rules:
|
||||
|
||||
- keep Browser Node mechanics in this package and host/product-specific methods
|
||||
in the consuming app or integration
|
||||
- require hosts to provide bridge namespaces; the package must not assume
|
||||
`__tutti`, `__tsh`, or any other product global
|
||||
- keep preview proxy interfaces inert until a host intentionally implements
|
||||
route resolution
|
||||
- keep daemon contracts out of Browser Node v1; the desktop host persists layout
|
||||
through the existing Workbench snapshot
|
||||
|
||||
### `packages/configs/*`
|
||||
|
||||
Config packages exist to keep engineering defaults centralized and reusable.
|
||||
|
||||
They should stay small and boring.
|
||||
|
||||
### `packages/ui/*`
|
||||
|
||||
UI packages define shared frontend foundations.
|
||||
|
||||
Current packages:
|
||||
|
||||
- `packages/ui/system`: shared tokens, icons, styles, and primitives for renderer consumers; also the repository-owned host package for shared shadcn CLI and Radix primitive acquisition
|
||||
- `packages/ui/i18n-runtime`: host-agnostic i18n runtime helpers for shared frontend packages and app-level runtime composition
|
||||
- `packages/ui/react-hooks`: host-agnostic React hook helpers for shared frontend packages, including external-store snapshot and selector patterns
|
||||
|
||||
Rules:
|
||||
|
||||
- keep scope limited to frontend foundation concerns such as visual-system primitives, token-backed styles, host-agnostic i18n runtime composition, and host-agnostic React subscription helpers
|
||||
- allow `ui/*` to own host-agnostic React hook foundations when the hook pattern is shared across packages and stays free of product workflows
|
||||
- prefer routing shared `useSyncExternalStore` wiring through `packages/ui/react-hooks` instead of rebuilding new subscription wrappers in feature packages
|
||||
- do not move business components, product workflows, or domain orchestration into `ui/*`
|
||||
- prefer consuming `ui/*` from app renderers and reusable frontend packages rather than recreating the same foundations locally
|
||||
- prefer narrow, stable package entrypoints over exporting internal file layout as public API
|
||||
|
||||
### `packages/workbench/*`
|
||||
|
||||
Workbench packages define the shared workbench boundary for the open-source
|
||||
desktop and TSH.
|
||||
|
||||
Current packages:
|
||||
|
||||
- `packages/workbench/snapshot`: canonical TypeScript workbench snapshot types,
|
||||
migrations, normalization, validation, and JSON Schema. The daemon OpenAPI
|
||||
`WorkbenchSnapshot*` component schemas are synchronized from this package.
|
||||
- `packages/workbench/service`: shared Go Workbench snapshot service, validation,
|
||||
canonicalization, and persistence seam for daemon hosts.
|
||||
- `packages/workbench/electron`: Electron main-process Dock preview capture and
|
||||
bounded filesystem cache mechanics. Desktop hosts still own IPC
|
||||
authorization, BrowserWindow ownership, cache paths, and logging.
|
||||
- `packages/workbench/surface`: reusable workbench controller, reducer,
|
||||
placement, stacking, `WorkbenchHost`, React surface primitives, shell snapshot
|
||||
wiring, intent resolution, external-state render plumbing, and host/session
|
||||
lifecycle mechanics for projected presence, launch requests, transient
|
||||
activation, explicit close policy, and shell snapshot sanitation.
|
||||
|
||||
Rules:
|
||||
|
||||
- keep snapshot compatibility behavior in `snapshot`, not in app renderers
|
||||
- keep shared Go Workbench validation, canonicalization, and storage seams in
|
||||
`service`, not in host daemons
|
||||
- keep shared Electron Dock preview capture and bounded cache mechanics in
|
||||
`electron`; keep host window authorization and product diagnostics in the
|
||||
consuming desktop app
|
||||
- keep reusable workbench interaction mechanics in `surface`, not in
|
||||
product-specific feature UI
|
||||
- when `surface` exposes derived external-store snapshots through
|
||||
`getSnapshot()`, unchanged source snapshots must preserve reference identity;
|
||||
prefer the package-local derived-snapshot helper instead of rebuilding fresh
|
||||
objects or arrays on every read
|
||||
- keep product-specific node bodies, routing, and persistence adapters in the
|
||||
owning app or service
|
||||
- allow `surface` to own narrow default copy for generic workbench interaction
|
||||
mechanics such as window chrome labels; keep product-specific workbench copy
|
||||
in the owning app
|
||||
- do not widen `workbench/*` into a generic desktop shell package
|
||||
- keep package root exports intentionally small; root exports are the public
|
||||
interface, not an index of every internal module
|
||||
- do not export test fixtures, demo data, stack internals, reducer internals, or
|
||||
low-level hooks from a package root unless an existing consumer needs that as a
|
||||
stable interface
|
||||
- keep adapter-specific durable state behind generic contract fields such as
|
||||
`Record<string, unknown>` unless the adapter detail is itself part of the
|
||||
shared snapshot contract
|
||||
|
||||
Host reuse model:
|
||||
|
||||
1. Keep generic workbench interaction mechanics, structural styles, and narrow
|
||||
default copy in `packages/workbench/*`.
|
||||
2. Keep host-specific node bodies, routing, persistence adapters, and
|
||||
product-owned workbench copy in the consuming app or service.
|
||||
3. Let the consuming host create one app-level i18n runtime that merges:
|
||||
- host-owned i18n resources
|
||||
- reusable package default i18n resources
|
||||
4. Scope that runtime into package namespaces such as workbench window chrome
|
||||
instead of reconstructing per-package message objects by hand.
|
||||
|
||||
### `packages/workspace/*`
|
||||
|
||||
Workspace packages define reusable workspace-domain contracts that are intended
|
||||
to support a real multi-consumer boundary or a documented external contract as
|
||||
additional hosts adopt them.
|
||||
|
||||
Current packages:
|
||||
|
||||
- `packages/workspace/files`: Go domain kernel for logical workspace file
|
||||
semantics, path normalization, search scoring, and host-owned file adapters.
|
||||
- `packages/workspace/file-manager`: TypeScript state, actions, adapter
|
||||
contract, and optional React UI for a workspace file manager. Ownership
|
||||
boundaries live in that package’s `CONTRACT.md`.
|
||||
- `packages/workspace/terminal`: shared terminal node contract and frontend
|
||||
surface for workbench hosts.
|
||||
- `packages/workspace/issue-manager`: reusable issue-manager contracts, OpenAPI
|
||||
fragment, i18n defaults, React surface, and workbench registration helpers
|
||||
for workspace-scoped issue, task, and run workflows.
|
||||
|
||||
Release rule:
|
||||
|
||||
- npm package release participation is defined in the npm release conventions,
|
||||
not by repeating package rosters in architecture docs
|
||||
- shared non-npm modules follow their owning language and module conventions
|
||||
unless a separate release contract is introduced
|
||||
|
||||
Rules:
|
||||
|
||||
- keep host-specific adapters in the owning host, such as `services/tuttid` or
|
||||
an app renderer feature
|
||||
- a reusable frontend workspace package may still own shared session state,
|
||||
interaction flow, and optional React UI when those behaviors form the shared
|
||||
workspace-domain surface rather than a product-specific host integration
|
||||
- a reusable frontend workspace package may also own narrow default copy for its
|
||||
shared UI surface; hosts should override through their app-level i18n runtime
|
||||
rather than duplicating package strings locally
|
||||
- keep shared state and UI on logical workspace paths such as `/workspace`, not
|
||||
host absolute paths or VM mount paths
|
||||
- do not move tuttid storage lookup, desktop preload calls, TSH room mapping, or
|
||||
TACH-specific integration into `packages/workspace/*`
|
||||
|
||||
Host reuse model:
|
||||
|
||||
1. Reuse the shared package for session orchestration, view-model derivation,
|
||||
interaction flow, and optional UI when those behaviors are truly host-neutral.
|
||||
2. Implement host-specific transport and capability adapters in the consuming
|
||||
host, for example preload calls, daemon clients, room bridges, or local file
|
||||
selection surfaces.
|
||||
3. Keep shared workspace UI copy defaults in the owning package and merge them
|
||||
through the host's app-level i18n runtime instead of copying those strings
|
||||
into the host.
|
||||
4. Keep product-specific wording, shell integration, and user-facing host
|
||||
behaviors in the consuming host.
|
||||
|
||||
## Adding New Directories
|
||||
|
||||
### Add a new top-level directory only when
|
||||
|
||||
- the new area has a distinct deployment or ownership boundary
|
||||
- it cannot be described as part of an existing `apps/`, `services/`, `packages/`, `tools/`, or `docs/` area
|
||||
|
||||
### Add a new app directory when
|
||||
|
||||
- there is a new user-facing entrypoint with its own runtime shell
|
||||
|
||||
Examples:
|
||||
|
||||
- a desktop app
|
||||
- a CLI app
|
||||
|
||||
Keep future app ideas in docs until they become real modules. Do not reserve them as empty directories.
|
||||
|
||||
### Add a new service directory when
|
||||
|
||||
- there is a new backend process with its own lifecycle and state ownership
|
||||
|
||||
### Add a new package when
|
||||
|
||||
- there is a real multi-consumer boundary
|
||||
- the extracted API can be named narrowly by responsibility
|
||||
- the shared code is not just convenience reuse
|
||||
- the public entrypoint can stay much smaller than the implementation tree
|
||||
|
||||
Keep code local by default:
|
||||
|
||||
- desktop-only TypeScript stays in `apps/desktop`
|
||||
- daemon-only Go stays in `services/tuttid`
|
||||
|
||||
Keep future packages in docs, not in placeholder directories:
|
||||
|
||||
- a README-only package is usually a shallow module
|
||||
- a package name should appear in the tree only when contributors can follow it to a real interface and implementation
|
||||
|
||||
## Structure Review Questions
|
||||
|
||||
When reviewing a new directory or package, ask:
|
||||
|
||||
1. Which existing top-level area already owns this responsibility?
|
||||
2. Is this a real boundary or just an attempt to spread code out?
|
||||
3. Would keeping this code local be simpler and clearer?
|
||||
4. Is the new name based on responsibility instead of a vague shared label?
|
||||
5. Does the new structure reduce confusion, or just increase file count?
|
||||
6. Can a caller use the module through a small interface, or does the package
|
||||
root expose the implementation layout?
|
||||
Reference in New Issue
Block a user