ci/woodpecker/pr/ci Pipeline was successful
Removes prose semicolons outside code fences in the requirements contract (list items end with periods, clause joins split into sentences, M4 cell comma), replaces the em dash in the PRD T78 pointer with a colon, and normalizes the SITEMAP T78 line to colon and plain punctuation. Fenced-code semicolons untouched; no wording changes. Docs-only.
749 lines
36 KiB
Markdown
749 lines
36 KiB
Markdown
---
|
|
kind: spec
|
|
status: active
|
|
source_of_truth: true
|
|
---
|
|
|
|
# Official Mosaic CLI Capability and Tool Migration
|
|
|
|
- **Workstream:** T78
|
|
- **Status:** active requirements contract, implementation held by the M0 gates
|
|
- **Decision authority:** Jason Woltje
|
|
- **Design owner:** Vision
|
|
- **Integration trunk:** `next`
|
|
|
|
This contract is authoritative only on the integration trunk `next`. Branch copies are proposals.
|
|
Publication does not authorize implementation until the M0 milestone, task-graph, interface, and
|
|
partition gates pass.
|
|
|
|
## 1. Purpose
|
|
|
|
Migrate agent-facing operations from directly invoked scripts into documented, first-class command
|
|
groups in the existing TypeScript and Node.js `mosaic` CLI. The CLI becomes the stable interface
|
|
for operators, agents, the webUI, future seat containers, and future `mosaicd` execution.
|
|
|
|
The mission also phases out the installed `~/.config/mosaic/tools` script surface. Existing scripts
|
|
may remain private compatibility adapters only while measured consumers still require them.
|
|
|
|
## 2. Product alignment
|
|
|
|
Items 1 through 3 implement PRD D8 and D12:
|
|
|
|
1. The CLI is the primary execution surface.
|
|
2. The webUI uses Gateway APIs backed by the same official capability contracts.
|
|
3. A missing official capability is built before a webUI bypass is accepted.
|
|
|
|
This contract adds one explicit extension beyond D8 and D12: no harness, skill, or agent receives a
|
|
separate business-logic path around the CLI and Gateway capability contract.
|
|
|
|
This contract does not replace the fleet north star, issue `#1382`, the fleet configuration
|
|
contract `#758`, the exact fleet communications contract `#766`, or future container and `mosaicd`
|
|
specifications. It defines the interfaces those tracks consume.
|
|
|
|
## 3. Fixed decisions
|
|
|
|
| ID | Decision |
|
|
| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
| T78-D1 | Extend the existing official TypeScript and Node.js `mosaic` CLI. A second Python or shell entrypoint is forbidden. |
|
|
| T78-D2 | Expose documented groups such as `mosaic git`, `mosaic comms`, and `mosaic ci`. A generic public `mosaic tools` passthrough is forbidden. |
|
|
| T78-D3 | Resolve homes, endpoints, sockets, tool locations, and runtime paths through the central registry and one typed resolver. Commands do not hard-code them. |
|
|
| T78-D4 | One rootless container per seat is the target sandbox. It has a read-only root filesystem, no container-runtime socket, and lifecycle through future `mosaicd`. |
|
|
| T78-D5 | Dispatch is per-site. Localhost `orch-01` alone dispatches USC-seat implementation. Homelab `orch-01` alone dispatches homelab-seat implementation and homelab-owned surfaces. |
|
|
| T78-D6 | Tmux and fleet-comms remain temporary communications adapters behind a transport-neutral CLI contract. |
|
|
| T78-D7 | Decommissioning is phased and mechanically enforced. Removal requires zero measured consumers and a discriminating planted-reference control. |
|
|
|
|
Derived security boundary:
|
|
|
|
- `~/.mosaic/tools` is canonical working source during migration. It is not automatically trusted
|
|
runtime installation state.
|
|
- Reviewed source is promoted into installed or packaged runtime artifacts.
|
|
- A multi-writer brain-repository push must not silently replace credential-bearing executable code
|
|
used by every seat.
|
|
|
|
## 4. Explicitly rejected alternatives
|
|
|
|
| Alternative | Rejection reason |
|
|
| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
|
|
| Separate Python CLI | Creates a second contract, release path, and policy surface. |
|
|
| Public `mosaic tools <script>` passthrough | Preserves script names and paths as the API instead of defining capabilities. |
|
|
| CLI allowlists as the sandbox | Parser allowlists do not isolate files, credentials, processes, networks, or container control. |
|
|
| Execute the synced working tree as the final runtime | A brain push would become host-wide code execution authority. |
|
|
| Big-bang script rewrite and deletion | Mature queue, identity, credential, and uncertainty behavior would be changed without parity evidence. |
|
|
| Tmux-shaped communications API | It would force future Matrix or native transports to preserve tmux concepts. |
|
|
|
|
## 5. Terminology
|
|
|
|
- **Central registry:** the schema-v1 `config.json` authority filed in issue `#1382`.
|
|
- **Registry resolver:** the typed reader that validates and resolves central-registry values.
|
|
- **Capability catalog:** the typed inventory of public capability identifiers and behavior. It is
|
|
not the central registry.
|
|
- **Capability policy:** data that maps verified actor and lane identity to allowed capabilities and
|
|
scopes.
|
|
- **Local adapter:** a temporary in-process or private-script implementation used before `mosaicd`
|
|
is available.
|
|
- **Broker adapter:** the future client transport to `mosaicd` outside the seat container.
|
|
- **Installed legacy tree:** `~/.config/mosaic/tools`.
|
|
- **Canonical working source:** `~/.mosaic/tools` during the migration period.
|
|
- **Runtime artifact:** reviewed package or installed bytes actually executed by a seat.
|
|
|
|
## 6. Public CLI grammar
|
|
|
|
### CLI-REQ-001: First-class command groups
|
|
|
|
The official help surface MUST register domain groups directly:
|
|
|
|
```text
|
|
mosaic git ...
|
|
mosaic comms ...
|
|
mosaic ci ...
|
|
```
|
|
|
|
Future domains MAY include `infra`, `identity`, and other reviewed capability families. They MUST
|
|
NOT appear through a generic script dispatcher.
|
|
|
|
### CLI-REQ-002: Stable command shape
|
|
|
|
New capability commands use this grammar:
|
|
|
|
```text
|
|
mosaic <domain> <resource> <verb> [target] [options]
|
|
```
|
|
|
|
The first pilot freezes these paths:
|
|
|
|
```text
|
|
mosaic git issue list
|
|
mosaic git issue view <number>
|
|
mosaic git issue comment <number> --input <path|->
|
|
```
|
|
|
|
Capability identifiers are independent from display text:
|
|
|
|
| Command | Capability ID | Class |
|
|
| -------------------------- | ------------------- | ---------------- |
|
|
| `mosaic git issue list` | `git.issue.list` | read |
|
|
| `mosaic git issue view` | `git.issue.view` | read |
|
|
| `mosaic git issue comment` | `git.issue.comment` | bounded mutation |
|
|
|
|
Renaming a command path does not silently rename its capability identifier. Either change requires a
|
|
versioned compatibility decision.
|
|
|
|
### CLI-REQ-003: Common targeting options
|
|
|
|
The pilot supports:
|
|
|
|
- `--instance <name>` for the configured provider instance.
|
|
- `--repo <owner/name>` for the provider repository.
|
|
- `--format <table|json>` for output selection.
|
|
- `--correlation-id <id>` for a caller-supplied valid identifier. Omission generates one.
|
|
- `--idempotency-key <key>` for mutations. Omission generates one and returns it.
|
|
|
|
An instance may be inferred only when the registry has exactly one valid instance for that domain.
|
|
A repository may be inferred only from a validated current repository declaration and an
|
|
unambiguous canonical remote. Ambiguity fails closed and names the missing field.
|
|
|
|
No public option forces local compatibility mode when policy selected broker mode. A caller cannot
|
|
downgrade the execution boundary.
|
|
|
|
### CLI-REQ-004: Mutation input
|
|
|
|
`git.issue.comment` reads its body from `--input <path>` or stdin with `--input -`. The CLI MUST:
|
|
|
|
1. reject a missing or empty body.
|
|
2. apply a documented byte limit before provider access.
|
|
3. never place the body in process arguments, diagnostics, or audit metadata.
|
|
4. compute a body digest for read-back verification without exposing the body.
|
|
5. avoid automatic retry after an uncertain provider mutation.
|
|
|
|
### CLI-REQ-005: Structured result envelope
|
|
|
|
JSON output uses one versioned envelope:
|
|
|
|
```ts
|
|
interface CapabilityResultV1<T> {
|
|
schemaVersion: 1;
|
|
capabilityId: string;
|
|
status: 'succeeded' | 'invalid' | 'denied' | 'failed' | 'uncertain' | 'unavailable';
|
|
executionMode: 'local-adapter' | 'mosaicd';
|
|
identityTrust: 'local-asserted' | 'runtime-verified';
|
|
correlationId: string;
|
|
idempotencyKey?: string;
|
|
target: Record<string, string | number | boolean | null>;
|
|
data?: T;
|
|
diagnostics: Array<{
|
|
code: string;
|
|
message: string;
|
|
field?: string;
|
|
retryable: boolean;
|
|
}>;
|
|
audit:
|
|
| { authority: 'mosaicd'; recorded: true; eventId: string }
|
|
| { authority: 'none'; recorded: false; localEventId?: string };
|
|
}
|
|
```
|
|
|
|
`target` and `diagnostics` contain no credentials or unbounded provider body. Table output is a
|
|
human view of the same result and cannot carry a different verdict.
|
|
|
|
### CLI-REQ-006: Exit behavior
|
|
|
|
| Exit | Meaning |
|
|
| ---: | --------------------------------------------------------------------------- |
|
|
| 0 | `succeeded` |
|
|
| 2 | `invalid`: invalid input, invalid configuration, or unsupported schema |
|
|
| 3 | `denied` by capability or scope policy |
|
|
| 4 | `failed` with a confirmed non-success outcome |
|
|
| 5 | `uncertain`, including a mutation whose provider result cannot be confirmed |
|
|
| 6 | `unavailable`, including missing broker, credentials, or required adapter |
|
|
|
|
A provider HTTP success alone is insufficient. The adapter validates the expected response shape.
|
|
A mutation that may have landed but lacks confirmation returns exit 5 and is never described as
|
|
failed or safe to retry. For a provider-native idempotent mutation, manual reconciliation MAY retry
|
|
the same key. For `uncertain-no-retry`, help directs the caller to a read-back check and forbids
|
|
mutation retry.
|
|
|
|
### CLI-REQ-007: Help and discovery
|
|
|
|
The capability catalog generates or validates:
|
|
|
|
- `mosaic --help` command-group listing.
|
|
- group and command help.
|
|
- stable capability identifiers.
|
|
- machine-readable capability discovery.
|
|
- documentation tables.
|
|
- policy-generation inputs.
|
|
- tests that reject undocumented public commands and orphaned capabilities.
|
|
|
|
## 7. Central registry resolver
|
|
|
|
### CFG-REQ-001: One distinct resolver
|
|
|
|
Implement one exported resolver named `MosaicRegistryResolver` or another name explicitly approved
|
|
in the contract review. It MUST NOT be named `ConfigService`. The existing
|
|
`packages/mosaic/src/config/config-service.ts` exports `ConfigService` for SOUL, USER, and TOOLS
|
|
content and remains a separate concern.
|
|
|
|
### CFG-REQ-002: Frozen schema consumption
|
|
|
|
The resolver consumes schema v1 from issue `#1382` without creating parallel keys. Every key is
|
|
optional. The exact v1 surface is:
|
|
|
|
- `$schema`, with the known marker `mosaic-config-v1`.
|
|
- `mosaicHome`, reserved, null, and without a v1 consumer.
|
|
- `brainHome`, default `~/.mosaic`.
|
|
- `instances.gitea.<name>.url`.
|
|
- `fleet.socket`.
|
|
- `harnessConfig.pi.agentDir`.
|
|
- `harnessConfig.claude.configDir`.
|
|
- `harnessConfig.claude.secureStorageDir`.
|
|
|
|
Credential values, model and effort defaults, and `fleet.rosterPath` are forbidden. A non-null
|
|
`mosaicHome` value fails validation because v1 reserves the field without implementing relocation.
|
|
An absent or null `$schema` is interpreted as v1, the exact `mosaic-config-v1` marker is accepted,
|
|
and every other non-null marker fails before value resolution.
|
|
|
|
Absent or null values select the framework default. A `~` path prefix expands at read time and is
|
|
never rewritten into the user file. Unknown top-level and nested keys warn loudly and are ignored
|
|
for rolling-version compatibility. Every warning and machine-readable diagnostic names the full
|
|
ignored key path, so a typo is visible at every read.
|
|
|
|
Fail-closed read behavior applies to invalid JSON, a failed C1 version check, a known key with an
|
|
invalid type or value, and a present but empty or invalid override. An optional
|
|
`mosaic registry validate` lint mode MAY reject unknown keys for operator validation, but the normal
|
|
resolver read path does not. This top-level group is separate from the existing `mosaic config`
|
|
commands backed by `ConfigService`.
|
|
|
|
### CFG-REQ-003: Resolution precedence
|
|
|
|
For each supported value, resolution follows exactly:
|
|
|
|
1. the schema-defined `MOSAIC_<KEY>_OVERRIDE` environment override.
|
|
2. validated `config.json` value.
|
|
3. one centralized framework default, when the key defines a default.
|
|
|
|
A present override always wins. An empty or invalid override fails and does not fall through to the
|
|
file or default. `$schema` and reserved `mosaicHome` have no environment override. Consumed values
|
|
use this collision-free mapping:
|
|
|
|
| Registry key | Environment override |
|
|
| --------------------------------------- | ---------------------------------------------------------- |
|
|
| `brainHome` | `MOSAIC_BRAIN_HOME_OVERRIDE` |
|
|
| `fleet.socket` | `MOSAIC_FLEET_SOCKET_OVERRIDE` |
|
|
| `harnessConfig.pi.agentDir` | `MOSAIC_HARNESS_CONFIG_PI_AGENT_DIR_OVERRIDE` |
|
|
| `harnessConfig.claude.configDir` | `MOSAIC_HARNESS_CONFIG_CLAUDE_CONFIG_DIR_OVERRIDE` |
|
|
| `harnessConfig.claude.secureStorageDir` | `MOSAIC_HARNESS_CONFIG_CLAUDE_SECURE_STORAGE_DIR_OVERRIDE` |
|
|
| `instances.gitea.<name>.url` | `MOSAIC_INSTANCES_GITEA_<NAME>_URL_OVERRIDE` |
|
|
|
|
Gitea instance names match `[a-z][a-z0-9-]*`. The override name uppercases the instance name and
|
|
maps hyphen to underscore. Underscores are not valid in source instance names, so two valid names
|
|
cannot flatten to the same override.
|
|
|
|
A value without a valid result fails before adapter or provider access. Invalid known URLs, socket
|
|
names, paths, and value types fail closed. Unknown keys follow CFG-REQ-002.
|
|
|
|
### CFG-REQ-004: Typed provenance
|
|
|
|
Every resolved value carries non-secret provenance:
|
|
|
|
```ts
|
|
type RegistryValueSource = 'override' | 'registry' | 'framework-default';
|
|
|
|
interface ResolvedRegistryValue<T> {
|
|
key: string;
|
|
value: T;
|
|
source: RegistryValueSource;
|
|
schemaVersion: 1;
|
|
}
|
|
```
|
|
|
|
Machine-readable diagnostics include the full path of every ignored unknown key. Diagnostics may
|
|
name a known key and source class. They do not emit credential values or unrelated configuration.
|
|
|
|
### CFG-REQ-005: Bootstrap and path safety
|
|
|
|
Registry discovery is the fixed path `~/.config/mosaic/config.json`. It has no v1 search path and no
|
|
alternate location. The file is the one user-updatable path inside `~/.config/mosaic` and is
|
|
protected by a deny-wins upgrade carve-out. Upgrades never overwrite user edits.
|
|
|
|
This fixed bootstrap avoids circular dependence on reserved `mosaicHome`. A seat container reads its
|
|
own internal `~/.config/mosaic/config.json`, supplied by the container topology, rather than a host
|
|
path or a relocation flag. Path values are expanded, normalized, validated, and tested under at
|
|
least two distinct home roots.
|
|
|
|
No command embeds home directories, script locations, provider endpoints, seat paths, or tmux socket
|
|
names outside the resolver and its reviewed defaults.
|
|
|
|
### CFG-REQ-006: Schema evolution
|
|
|
|
A new key requires:
|
|
|
|
1. a named consumer.
|
|
2. a `#1382` schema amendment.
|
|
3. joint ACK from the frozen-schema and resolver-contract custodians until handoff, recorded by
|
|
custodian-authored commits rather than relayed tokens alone.
|
|
4. parser, invalid-input, default, and two-root tests.
|
|
5. documentation in the same reviewed change.
|
|
|
|
Speculative keys are forbidden.
|
|
|
|
### CFG-REQ-007: Joint freeze evidence
|
|
|
|
The v1 resolver contract is jointly frozen:
|
|
|
|
- Fred, frozen-schema custodian, accepted C1 and C3 through token
|
|
`CLI-T78-REGISTRY-FREEZE ACCEPT`, then accepted amended C2 through token
|
|
`CLI-T78-REGISTRY-C2 ACCEPT`.
|
|
- Homelab `orch-01`, issue and resolver-contract custodian, accepted C1 and C3 and supplied the
|
|
adopted C2 rolling-version amendment in the fleet-comms repository, message
|
|
`sites/usc/20260827T004509Z__to-vision__from-homelab.orch-01__683e4c.md`, blob
|
|
`35a7c4c1e54eb9196abeef3135d211ee1dfc46db`.
|
|
|
|
Durable lane provenance is recorded in the Mosaic brain repository at
|
|
`fleet/lanes/cli-migration/registry-freeze-evidence.md` and the independent custodian-authored
|
|
`fleet/lanes/cli-migration/registry-freeze-fred-ack.md`. Schema evolution after this freeze still
|
|
follows CFG-REQ-006.
|
|
|
|
## 8. Capability catalog and policy
|
|
|
|
### CAP-REQ-001: One typed catalog
|
|
|
|
Each capability definition records:
|
|
|
|
```ts
|
|
type CapabilityEffect = 'read' | 'bounded-mutation' | 'privileged-mutation';
|
|
|
|
interface CapabilityDefinitionV1 {
|
|
id: string;
|
|
commandPath: readonly string[];
|
|
effect: CapabilityEffect;
|
|
targetSchema: string;
|
|
inputSchema: string;
|
|
outputSchema: string;
|
|
credentialClass: string | null;
|
|
requiredScopes: readonly string[];
|
|
auditRequired: boolean;
|
|
timeoutMs: number;
|
|
idempotency: 'read' | 'required-key' | 'provider-native' | 'uncertain-no-retry';
|
|
adapterId: string;
|
|
deprecation: 'active' | 'deprecated' | 'removed';
|
|
}
|
|
```
|
|
|
|
The catalog is data consumed by the parser, help, policy, documentation, and tests. Command handlers
|
|
must not maintain independent copies of these facts.
|
|
|
|
### CAP-REQ-002: Policy is not parser logic
|
|
|
|
Capability grants map verified actor identity and lane to capability IDs and resource scopes. They
|
|
are data. A named seat receives no authority from its name alone.
|
|
|
|
The user-editable central registry is placement and endpoint configuration, not authorization
|
|
policy. It MUST NOT contain lane grants or let a seat self-grant capability scope. Target authority
|
|
lives in the `mosaicd` control-plane store outside seat containers and returns a policy revision and
|
|
digest with every decision.
|
|
|
|
Before `mosaicd`, local compatibility mode may evaluate a package-owned policy for behavior and test
|
|
parity, but it reports locally asserted identity and makes no broker-grade authorization claim. Mode
|
|
selection is declared by topology and policy, never inferred from broker availability. A missing or
|
|
unhealthy required broker returns `unavailable`. It never falls back to local mode.
|
|
|
|
A capability using a shared, service, operator, or admin credential is broker-only. Local mode may
|
|
use only the acting seat's own credential against a registry endpoint. Privileged infrastructure,
|
|
merge, deployment, identity, authorization, and secret-management cutover requires `mosaicd`. A
|
|
future policy-store key or broker endpoint still requires CFG-REQ-006 and the `mosaicd` topology
|
|
contract.
|
|
|
|
### CAP-REQ-003: Identity trust
|
|
|
|
CLI arguments and ordinary environment variables are actor hints, not authorization identity. The
|
|
local adapter reports that identity is locally asserted and MUST NOT claim broker-grade
|
|
authorization. `mosaicd` derives or verifies actor identity from the authenticated seat runtime.
|
|
|
|
### CAP-REQ-004: Positive and denied controls
|
|
|
|
Every capability test includes:
|
|
|
|
1. an allowed request with expected result.
|
|
2. a denied request differing only in the relevant lane or scope.
|
|
3. a malformed target or configuration denial.
|
|
4. a credential-redaction assertion.
|
|
5. a verdict-discrimination control that proves the test can fail.
|
|
|
|
## 9. Adapter and broker contract
|
|
|
|
### EXE-REQ-001: One capability request
|
|
|
|
```ts
|
|
interface CapabilityRequestV1 {
|
|
schemaVersion: 1;
|
|
capabilityId: string;
|
|
actorHint?: { seat?: string; lane?: string };
|
|
target: Record<string, string | number | boolean | null>;
|
|
arguments: Record<string, string | number | boolean | null>;
|
|
correlationId: string;
|
|
idempotencyKey?: string;
|
|
}
|
|
```
|
|
|
|
Credential values and unbounded comment bodies are not serialized into audit-safe request metadata.
|
|
Body content travels through a bounded private input channel appropriate to the adapter.
|
|
|
|
### EXE-REQ-002: Local compatibility adapter
|
|
|
|
The local adapter MAY call a reviewed in-process implementation or a private script adapter. It
|
|
MUST preserve existing queue guards, wrapper-first behavior, credential resolution, response
|
|
validation, and mutation uncertainty. It reports `executionMode: local-adapter` and
|
|
`identityTrust: local-asserted`.
|
|
|
|
Private child adapters receive bodies and credentials only through stdin, owner-only temporary
|
|
files, or inherited file descriptors, never child-process arguments. Captured child stderr, shell
|
|
trace, and diagnostics are inside the redaction boundary. Local results always use
|
|
`audit: { authority: 'none', recorded: false }`. A local event identifier is not authoritative
|
|
audit evidence.
|
|
|
|
The local adapter is compatibility, not a sandbox or authorization claim.
|
|
|
|
### EXE-REQ-003: `mosaicd` broker adapter
|
|
|
|
The broker adapter sends the same logical request to `mosaicd` outside the seat container.
|
|
`mosaicd` owns:
|
|
|
|
- authoritative seat identity, recorded in audit from the derived runtime identity rather than
|
|
`actorHint`.
|
|
- capability and scope authorization.
|
|
- credential resolution.
|
|
- operation execution.
|
|
- output sanitization.
|
|
- audit persistence.
|
|
- bounded timeout and cancellation behavior.
|
|
|
|
A contradictory `actorHint` produces a diagnostic and never replaces the derived actor. Broker
|
|
results report `identityTrust: runtime-verified`. `audit.recorded: true` is valid only after
|
|
`mosaicd` confirms persistence and returns its event ID. Consumers verify authoritative evidence
|
|
against the broker trail, not the seat-produced envelope alone.
|
|
|
|
The transport and endpoint are supplied by immutable container topology and the reviewed central
|
|
registry contract. No command hard-codes a daemon socket.
|
|
|
|
### EXE-REQ-004: Packaged implementation boundary
|
|
|
|
The initial TypeScript layout is:
|
|
|
|
- `packages/mosaic/src/central-registry/` for `MosaicRegistryResolver`, schema, and provenance.
|
|
- `packages/mosaic/src/capabilities/` for catalog, request, result, policy interfaces, and tests.
|
|
- `packages/mosaic/src/capabilities/adapters/local/` for temporary local adapter modules.
|
|
- `packages/mosaic/src/capabilities/adapters/mosaicd/` for the broker client seam.
|
|
- `packages/mosaic/src/commands/git.ts`, with later first-class domain files following the same
|
|
command pattern.
|
|
|
|
Remaining script implementations may be promoted under `packages/mosaic/framework/tools/` as
|
|
private packaged adapters during transition. Their installed paths are resolver-owned and are not
|
|
public command contracts. No production adapter imports or executes source from the brain working
|
|
tree as the final path.
|
|
|
|
### EXE-REQ-005: Container boundary
|
|
|
|
The representative seat container has:
|
|
|
|
- one seat identity.
|
|
- rootless execution.
|
|
- read-only root filesystem, with explicit bounded writable mounts.
|
|
- a read-only internal `~/.config/mosaic/config.json` supplied by topology.
|
|
- no host credential tree.
|
|
- no shared host or fleet tmux socket.
|
|
- a dedicated per-seat tmux socket only for one named, reviewed temporary adapter with a stated
|
|
removal stage.
|
|
- no Docker, Podman, or other container-runtime socket.
|
|
- no installed legacy tool tree mount.
|
|
- network access limited to declared capability paths.
|
|
|
|
Container implementation is outside this mission. Contract and compatibility tests are inside it.
|
|
|
|
## 10. Communications portability
|
|
|
|
### COM-REQ-001: Transport-neutral public contract
|
|
|
|
Public communications capabilities use logical addresses, messages, correlation IDs, delivery
|
|
status, and adapter diagnostics. Tmux pane, socket, retry, and draft details stay below the public
|
|
contract.
|
|
|
|
### COM-REQ-002: Transitional semantics
|
|
|
|
The tmux adapter preserves the measured `rc=2` behavior: content reached a pane as a draft, so the
|
|
operation is not retried automatically. Fleet-comms preserves durable cross-site message identity
|
|
and acknowledgment behavior.
|
|
|
|
### COM-REQ-003: Future transport replacement
|
|
|
|
A Matrix or native transport implementation passes the same contract tests. Callers do not change
|
|
command paths, capability IDs, or result interpretation when the adapter changes.
|
|
|
|
## 11. Canonical source and runtime integrity
|
|
|
|
### SRC-REQ-001: Reviewed baseline
|
|
|
|
The F11 baseline is commit `5be5825`. Inventory report `585f214`, code review `3fe8de7`, and
|
|
security review `e270098` are the M0 evidence. Both reviews found no blocker.
|
|
|
|
### SRC-REQ-002: Required M1 corrections
|
|
|
|
Before expanding direct execution from the working tree:
|
|
|
|
1. fix the `check-helper-drift.sh` environment assignment that suppresses version diagnostics.
|
|
2. strip 20 dangling Excalidraw `node_modules` symlinks.
|
|
3. add `tools/**/node_modules/` to the brain `.gitignore`.
|
|
4. keep the reviewed `package-lock.json` as the reproducible dependency contract.
|
|
5. correct the baseline report's misleading path-count headline.
|
|
6. move `ci-publish-watch.sh` credential headers from process arguments to curl stdin
|
|
configuration when that suite is changed.
|
|
|
|
### SRC-REQ-003: Source is not installation
|
|
|
|
Runtime code is loaded from reviewed package or installed artifacts, not directly from a mutable
|
|
multi-writer checkout as the final design. Any transitional direct execution requires:
|
|
|
|
- a protected-path review rule.
|
|
- an accepted digest anchored outside the synced tree in reviewed package metadata or Stack source.
|
|
- verification before execution, including every credential-helper invocation.
|
|
- a periodic verifier whose mismatch alert reaches a human.
|
|
- a stated removal point.
|
|
|
|
### SRC-REQ-004: Credential helper integrity
|
|
|
|
The host-wide git credential helper and its accepted pin cannot be replaceable by the same synced
|
|
commit. Transition requires an independently anchored verifier and alert. Final state moves the
|
|
helper into the reviewed runtime installation or another explicitly protected location.
|
|
|
|
## 12. Migration and decommission
|
|
|
|
### MIG-REQ-001: Consumer census
|
|
|
|
Inventory every direct caller of `~/.config/mosaic/tools`, grouped as:
|
|
|
|
- skills and guides.
|
|
- hooks and generated harness configuration.
|
|
- systemd units and timers.
|
|
- launchers and provisioning.
|
|
- tests and CI.
|
|
- direct agent commands.
|
|
- private tool-to-tool calls.
|
|
- production consumers.
|
|
|
|
Each census run creates a fresh randomized planted legacy reference at a unique path and is valid
|
|
only when the detector reports that run's exact plant. Every host at every site still running the
|
|
installed legacy tree is censused independently. An empty result without the fresh control, or a
|
|
zero from only one host, is not evidence.
|
|
|
|
### MIG-REQ-002: Risk-ordered waves
|
|
|
|
Migrate in this order:
|
|
|
|
1. read-only status, health, list, and view.
|
|
2. bounded CI and communications.
|
|
3. issue, pull-request, and milestone mutation.
|
|
4. credentialed infrastructure.
|
|
5. merge, deployment, identity, authorization, and secret management.
|
|
|
|
Each wave proves contract parity before consumer cutover. Waves 1 through 3 may use local mode with
|
|
acting-seat credentials. Wave 4 cutover is broker-only when it uses a shared or service credential.
|
|
Wave 5 cutover is always broker-only and begins only after the M6 `mosaicd` boundary gate passes.
|
|
|
|
### MIG-REQ-003: Protected consumers
|
|
|
|
- M365 credentials, AD status, and six production consumers remain Peggy-owned until exact signoff
|
|
and timer-aware tests.
|
|
- Fleet-doctor, seat-service, Woodpecker extras, and their units remain Veronica-owned until exact
|
|
replacement proof and named handoff.
|
|
- Brain guards are excluded from wholesale removal.
|
|
- The active A2 hold applies to `tools/seat-service/` and
|
|
`fleet/bin/launch-seat-claude.sh` only.
|
|
- Fleet configuration issue `#758` retains its own normative contract and delivery DAG. T78 does
|
|
not re-scope or absorb its missing `inspect` and `validate` verbs. T78 measures and consumes the
|
|
stable fleet surface only after `#758` completion or an explicit owner handoff.
|
|
|
|
### MIG-REQ-004: Compatibility and deprecation
|
|
|
|
Compatibility shims are private and time-bounded. Each shim:
|
|
|
|
- names its public replacement.
|
|
- preserves existing safety behavior.
|
|
- emits a machine-detectable deprecation diagnostic without corrupting JSON output.
|
|
- has a measured consumer and removal issue.
|
|
- cannot be used to add new direct callers.
|
|
|
|
### MIG-REQ-005: Final removal
|
|
|
|
The installed `~/.config/mosaic/tools` script surface is removed only after:
|
|
|
|
1. all active consumers use official capabilities.
|
|
2. the census reports zero with a firing planted control.
|
|
3. Constitution and wrapper-first gates are mechanically enforced by the CLI path.
|
|
4. systemd units are regenerated, daemon-reloaded, re-enabled, and behavior-tested.
|
|
5. fleet-doctor state is preserved.
|
|
6. clean install, upgrade, rollback, and stale-install tests pass.
|
|
7. user, admin, developer, API, and migration documentation is current.
|
|
|
|
## 13. Testing requirements
|
|
|
|
### TST-REQ-001: Resolver
|
|
|
|
- exact schema-v1 valid fixture.
|
|
- absent, null, exact-v1, and unknown-non-null `$schema` cases.
|
|
- unknown top-level and nested key warnings with full-path diagnostics.
|
|
- `mosaic registry validate` lint rejection of the same unknown-key fixture.
|
|
- invalid URL, path, socket, and type failures.
|
|
- every precedence branch, including present-empty and present-invalid override denial without
|
|
fallback.
|
|
- two valid roots.
|
|
- container topology with a read-only internal registry and no host registry path.
|
|
- no credential value accepted or emitted.
|
|
- control proving the invalid fixture fails.
|
|
|
|
### TST-REQ-002: Capability catalog
|
|
|
|
- command and capability ID uniqueness.
|
|
- every public command documented.
|
|
- no orphan catalog record.
|
|
- parser, policy, help, and docs consume the same definition.
|
|
- unauthorized lane and scope denial.
|
|
- unknown capability denial.
|
|
- topology-selected mode never falls back when the required broker is unavailable.
|
|
- shared, service, operator, and admin credential classes reject local mode.
|
|
|
|
### TST-REQ-003: Pilot
|
|
|
|
- issue list and view against a valid configured instance.
|
|
- invalid instance and repository denial.
|
|
- comment success with provider response-shape and body-digest confirmation.
|
|
- comment denial before provider access.
|
|
- post-request uncertainty without retry, plus provider-native same-key and
|
|
`uncertain-no-retry` read-back reconciliation cases.
|
|
- credential, cookie, token, comment-body, child-argv, captured-stderr, and shell-trace redaction.
|
|
- local results prove `identityTrust: local-asserted` and `audit.recorded: false`.
|
|
- broker-stub results prove derived-identity precedence and reject unconfirmed
|
|
`audit.recorded: true`.
|
|
- user-editable endpoint changes cannot redirect a shared or service credential.
|
|
- local-adapter and broker-stub request/result seam parity at M3.
|
|
- live local-adapter and `mosaicd` contract parity at M6.
|
|
|
|
### TST-REQ-004: Migration
|
|
|
|
- fresh randomized consumer-census plant detected independently on every affected host and site.
|
|
- compatibility diagnostics in table and JSON modes.
|
|
- systemd timer and restart behavior.
|
|
- production M365/AD consumer probes.
|
|
- fleet-doctor digest-state preservation.
|
|
- clean install, upgrade, rollback, stale install, and greenfield operation.
|
|
- representative container without legacy tools mounted.
|
|
- representative container mounts no shared or fleet tmux socket, and any temporary tmux exception
|
|
uses only the named adapter's dedicated per-seat socket.
|
|
|
|
### TST-REQ-005: Delivery gates
|
|
|
|
Every source card requires focused tests, repository quality gates, independent code review,
|
|
security review for authorization, credentials, transport, or integrity surfaces, reviewed squash
|
|
PR to `next`, terminal-green CI, and linked-issue closure.
|
|
|
|
## 14. Documentation requirements
|
|
|
|
The workstream updates in the same delivery sequence:
|
|
|
|
- official CLI help.
|
|
- `docs/PRD.md` workstream pointer.
|
|
- `docs/ROADMAP.md` parallel-track entry.
|
|
- `docs/SITEMAP.md` requirements link.
|
|
- user guide commands and deprecation behavior.
|
|
- administrator configuration, migration, and recovery.
|
|
- developer architecture, capability authoring, schemas, and adapter contracts.
|
|
- API and machine-readable result schemas.
|
|
- release notes.
|
|
- T78 program-map and unified-roadmap records.
|
|
|
|
No command is public until its help, structured output, authorization behavior, and documentation
|
|
are present.
|
|
|
|
## 15. Delivery stages
|
|
|
|
| Stage | Scope | Exit gate |
|
|
| ----- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ |
|
|
| M0 | Register mission, reconcile ownership, establish and review source baseline, publish requirements and tracking | Reviewed contract merged, dedicated milestone and task graph present |
|
|
| M1 | Inventory consumers, normalize baseline, freeze registry resolver, capability catalog, policy, and runtime-integrity contracts | Typed interfaces and migration census reviewed |
|
|
| M2 | Implement resolver, catalog, common result envelope, and adapter interface | Contract and two-root tests green |
|
|
| M3 | Deliver pilot issue list, view, and comment | Allowed and denied controls, uncertainty behavior, docs, review, CI |
|
|
| M4 | Migrate waves 1 through 3, prepare wave 4 private adapters without shared-credential cutover | Per-suite owner handoff and parity evidence |
|
|
| M5 | Cut eligible consumers and generate harness policy | No new direct references, compatibility callers measured |
|
|
| M6 | Prove representative container and `mosaicd` seam, then cut over shared-credential wave 4 and all wave 5 capabilities | Boundary, authorization, audit, and parity tests green |
|
|
| M7 | Remove installed legacy script tree | Zero callers, migration and rollback evidence, docs and release gates complete |
|
|
|
|
## 16. Workstream acceptance
|
|
|
|
T78 completes only when:
|
|
|
|
1. the official TypeScript CLI exposes documented first-class capability groups.
|
|
2. the central registry resolver and capability catalog are single typed authorities.
|
|
3. two-root and container-topology tests prove no command-path hard-coding.
|
|
4. authorization has allowed and denied situational evidence.
|
|
5. agent-visible output, logs, and process arguments contain no credential values.
|
|
6. local and `mosaicd` modes share one request and result contract and report their mode honestly.
|
|
7. a representative rootless seat container performs granted operations without legacy tools,
|
|
host credentials, or a container-runtime socket.
|
|
8. tmux and fleet-comms can be replaced without changing public communications callers.
|
|
9. the legacy consumer census reaches zero with a discriminating control.
|
|
10. the installed `~/.config/mosaic/tools` script surface is removed.
|
|
11. independent review passes for every source partition.
|
|
12. all PRs are squash-merged to `next`, terminal CI is green, and linked issues are closed.
|
|
|
|
## 17. Contract-freeze status
|
|
|
|
The architecture inputs are frozen for independent review:
|
|
|
|
1. The central-registry resolver has joint C1, amended C2, and C3 approval.
|
|
2. User-editable `config.json` is not authorization policy. Target grant authority belongs to
|
|
`mosaicd`. Local mode is explicitly non-authoritative.
|
|
3. Registry, capability, and adapter source boundaries are packaged TypeScript modules. Brain tools
|
|
remain working source and temporary private adapters, not the final runtime contract.
|
|
4. Issue `#758` remains an independent dependency and is not re-scoped into T78.
|
|
|
|
Provider tracking remains operationally blocked until the `orch-01` Mosaic Stack credential slot is
|
|
minted. This does not weaken the contract or authorize implementation before reviewed publication.
|