chore: commit work in progress before registrar reconciliation
Authorised as part of the CUST-WP-0068 identity cleanup. The registrar requires a clean worktree, and these changes were already present in the checkout. Refs CUST-WP-0068 Assistant: claude-code Assistant-Model: opus Assistant-Process: 2583210@bnt-lap001 Assistant-Session: f2bff2d5-e9b2-4338-92ca-10282a927006
This commit is contained in:
parent
c62c580575
commit
dca3498237
4 changed files with 555 additions and 2 deletions
6
SCOPE.md
6
SCOPE.md
|
|
@ -19,6 +19,8 @@ coordination-engine captures coordination models, specs, and registry entries fo
|
|||
## In Scope
|
||||
|
||||
- Coordination specs, history, and registry indexes
|
||||
- Headless coordination runtime, including cross-repository worker coordination
|
||||
(observation, leases, wake-up, checkpoints, safety gates, and receipts)
|
||||
- State Hub workplans and agent instructions
|
||||
- Capability registration when coordination patterns stabilize
|
||||
|
||||
|
|
@ -26,6 +28,6 @@ coordination-engine captures coordination models, specs, and registry entries fo
|
|||
|
||||
## Out of Scope
|
||||
|
||||
- Runtime orchestration engine implementation (future repos)
|
||||
- Replacing the systems coordinated through adapters (issue trackers, chat,
|
||||
workflow, notification, delivery, or evidence systems)
|
||||
- Replacing issue trackers or chat systems
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,12 @@
|
|||
| --- | --- | --- | --- | --- |
|
||||
| workplan | COORDINATION-WP-0001 | finished | — | workplans/COORDINATION-WP-0001-statehub-bootstrap.md |
|
||||
| workplan | COORDINATION-WP-0002 | finished | — | workplans/COORDINATION-WP-0002-coordination-model-spec.md |
|
||||
| workplan | COORDINATION-WP-0003 | ready | — | workplans/COORDINATION-WP-0003-worker-coordination-service.md |
|
||||
| task | COORDINATION-WP-0001-T01 | done | — | workplans/COORDINATION-WP-0001-statehub-bootstrap.md |
|
||||
| task | COORDINATION-WP-0001-T02 | done | — | workplans/COORDINATION-WP-0001-statehub-bootstrap.md |
|
||||
| task | COORDINATION-WP-0001-T03 | done | — | workplans/COORDINATION-WP-0001-statehub-bootstrap.md |
|
||||
| task | COORDINATION-WP-0002-T01 | done | — | workplans/COORDINATION-WP-0002-coordination-model-spec.md |
|
||||
| task | COORDINATION-WP-0003-T01 | done | — | workplans/COORDINATION-WP-0003-worker-coordination-service.md |
|
||||
| task | COORDINATION-WP-0003-T02 | wait | — | workplans/COORDINATION-WP-0003-worker-coordination-service.md |
|
||||
| task | COORDINATION-WP-0003-T03 | wait | — | workplans/COORDINATION-WP-0003-worker-coordination-service.md |
|
||||
| task | COORDINATION-WP-0003-T04 | wait | — | workplans/COORDINATION-WP-0003-worker-coordination-service.md |
|
||||
|
|
|
|||
443
spec/worker-coordination-service-v0.1.md
Normal file
443
spec/worker-coordination-service-v0.1.md
Normal file
|
|
@ -0,0 +1,443 @@
|
|||
# Worker Coordination Service v0.1
|
||||
|
||||
**Status:** Proposed contract
|
||||
**Owner:** coordination-engine (contract and runtime); State Hub and
|
||||
`tmux-amq` are external local adapters.
|
||||
**Request:** net-kingdom, “automatic worker wake-up and dependency coordination”
|
||||
|
||||
## 1. Problem and outcome
|
||||
|
||||
Several repository terminals run independent worker agents. Today an operator
|
||||
must repeatedly inspect each repository, relay results, and issue prompts that
|
||||
are effectively a scheduler. The service defined here turns State Hub changes
|
||||
into safe, deduplicated wake-ups while keeping repository agents responsible for
|
||||
publishing workplan/task/message state.
|
||||
|
||||
The desired loop is:
|
||||
|
||||
```text
|
||||
State Hub change
|
||||
-> observe and normalize
|
||||
-> determine actionable task/message
|
||||
-> acquire idempotent lease
|
||||
-> wake owning repo session
|
||||
-> agent resumes, checkpoints, and updates State Hub
|
||||
-> dependent work becomes actionable and is evaluated again
|
||||
```
|
||||
|
||||
The service does not execute repository code, invent task state, or replace
|
||||
State Hub as the source of truth. It does own the observation, lease, policy,
|
||||
checkpoint, and wake orchestration runtime.
|
||||
|
||||
## 2. Inputs and normalized trigger
|
||||
|
||||
The observer MUST support polling initially and MAY support a State Hub event
|
||||
subscription later. It watches:
|
||||
|
||||
* workplan status and task status/dependencies;
|
||||
* unread coordination messages and message read/ack state;
|
||||
* `needs_human` and intervention notes;
|
||||
* progress/checkpoint receipts.
|
||||
|
||||
Each source change is normalized to a trigger with an idempotency key:
|
||||
|
||||
```yaml
|
||||
WorkerTrigger:
|
||||
id: string
|
||||
source: workplan | task | message | checkpoint
|
||||
source_id: string
|
||||
source_revision: string
|
||||
target_repo: string
|
||||
target_agent: string?
|
||||
reason: task_actionable | dependency_satisfied | inbox_message | retry_due | checkpoint_resume
|
||||
observed_at: timestamp
|
||||
```
|
||||
|
||||
The idempotency key is `(source, source_id, source_revision, target_repo)`.
|
||||
Repeated observations MUST collapse to one pending trigger.
|
||||
|
||||
## 3. Actionability and safety gates
|
||||
|
||||
A trigger is actionable only when its task/workplan is active or ready, its
|
||||
dependencies are satisfied (or the message explicitly requests action), and no
|
||||
terminal safety gate applies. The service MUST stop and leave a durable receipt
|
||||
when any of these are true:
|
||||
|
||||
* `needs_human` is set or an intervention note requests review;
|
||||
* credentials, secrets, access tokens, or private key material are needed;
|
||||
* destructive, production, live, financial, or externally visible action is
|
||||
proposed without an approved policy/authority;
|
||||
* a policy decision, scope expansion, or ambiguous ownership requires a human;
|
||||
* the target session cannot be authenticated or its repository identity does not
|
||||
match the trigger.
|
||||
|
||||
Safety-gated work is never silently retried or rerouted to another agent.
|
||||
Retry behavior is configuration-driven: ordinary triggers use bounded
|
||||
exponential backoff, while safety-gated retries default to zero and may only be
|
||||
enabled by an explicit policy. No retry setting may bypass the safety gate.
|
||||
|
||||
## 4. Lease and deduplication protocol
|
||||
|
||||
When connected, coordination-engine atomically claims a short-lived coordination
|
||||
lease before waking an agent. Independently, `tmux-amq` maintains its own local
|
||||
queue lease so messages remain deliverable while coordination-engine is offline.
|
||||
The two leases are correlated but neither is the other's storage dependency:
|
||||
|
||||
Coordination-engine stores coordination leases, deduplication keys, and receipts
|
||||
in a local SQLite database. State Hub receives sanitized projections when it is
|
||||
available; it is not required for local queue delivery or lease recovery.
|
||||
|
||||
```yaml
|
||||
WorkerLease:
|
||||
trigger_id: string
|
||||
lease_id: string
|
||||
owner: coordination-engine
|
||||
target_repo: string
|
||||
target_agent: string?
|
||||
state: offered | acknowledged | running | checkpointed | completed | retry_wait | stopped
|
||||
attempt: integer
|
||||
acquired_at: timestamp
|
||||
expires_at: timestamp
|
||||
last_checkpoint_at: timestamp?
|
||||
coordination_endpoint_id: string?
|
||||
local_lease_id: string?
|
||||
```
|
||||
|
||||
Only one non-expired coordination lease may exist for a trigger. A wake request is retried
|
||||
with the same `lease_id`; the receiver MUST treat duplicate requests as no-ops.
|
||||
The agent acknowledges the lease before work begins, renews it while active,
|
||||
and releases it with a checkpoint or terminal result. Expiry moves the lease to
|
||||
`retry_wait` with bounded exponential backoff and an attempt limit. Exhaustion
|
||||
produces a stopped receipt for operator review.
|
||||
|
||||
## 5. Session wake contract
|
||||
|
||||
The runtime integrates with `tmux-amq`, a separate local repository that owns
|
||||
tmux session lifecycle, durable queueing, local leases, and PTY injection.
|
||||
`tmux-amq` MUST remain functional when coordination-engine is unavailable.
|
||||
Only repositories registered in gita may be addressed. A session may be started
|
||||
with, for example,
|
||||
`tamq --cmd "codex" net-kingdom railiance-platform`; the bridge opens one
|
||||
terminal per repository and runs the command. Messages addressed as
|
||||
`@repo: text` are queued/injected into that repository's terminal as
|
||||
`#sender-repo: text`. Coordination-engine calls the bridge through a local,
|
||||
authenticated adapter; it does not manipulate tmux directly.
|
||||
|
||||
Each tmux-amq endpoint is identified as `tmux-amq-<PID>`, where `<PID>` is the
|
||||
tmux server PID. Within one endpoint, a repository slug maps to exactly one
|
||||
tmux window; duplicate windows for the same repo are rejected or reconciled
|
||||
before attach. Different endpoint PIDs may independently host the same repo.
|
||||
|
||||
Outbound messages typed directly by an agent are detected through a tamq
|
||||
tmux-control-mode client. The client intercepts input lines beginning with
|
||||
`@<registered-repo>:` and submits a structured local message using the
|
||||
authenticated source window/repository. It does not wrap or replace the agent
|
||||
process. Control-mode parsing MUST preserve ordinary input unchanged and must
|
||||
not treat message-like text inside an unrelated multiline command as a message
|
||||
unless the configured parser recognizes a complete address line.
|
||||
|
||||
If tmux control-mode interception is unavailable, tamq leaves ordinary terminal
|
||||
use unchanged, marks interception unavailable in status/receipts, and does not
|
||||
fall back to pane scraping or unverified injection. Operators may explicitly
|
||||
use `tamq send @repo: message` as a degraded path.
|
||||
|
||||
tmux-amq MUST retain a local message history sufficient to inspect delivery
|
||||
state and export it to a messages file. It MUST also support replaying a
|
||||
messages file into a selected endpoint. Replay creates a new batch identifier,
|
||||
passes each entry through normal gita-target validation, policy checks, and
|
||||
deduplication, and records the original message ID as provenance. Replay MUST
|
||||
not bypass safety gates or silently overwrite an existing message.
|
||||
|
||||
History files use newline-delimited JSON (JSONL): one complete message envelope
|
||||
per line, including message ID, sender/target, body, timestamps, state, and
|
||||
replay provenance. JSONL exports are appendable and replayable as streams.
|
||||
|
||||
The repository is `tmux-amq`, but its executable is `tamq` (Tmux Agentic Message
|
||||
Queueing). It MUST provide conventional Unix CLI behavior, including
|
||||
`--help`/`-h`, `--version`/`-V`, non-zero exit status on errors, diagnostics on
|
||||
stderr, and machine-readable output options where commands produce records.
|
||||
|
||||
Default filesystem locations follow XDG conventions:
|
||||
|
||||
```text
|
||||
config: ${XDG_CONFIG_HOME:-$HOME/.config}/tamq/config.toml
|
||||
state: ${XDG_STATE_HOME:-$HOME/.local/state}/tamq/tamq.sqlite3
|
||||
socket: ${XDG_RUNTIME_DIR:-/tmp}/tamq.sock
|
||||
```
|
||||
|
||||
`TAMQ_CONFIG`, `TAMQ_STATE_DIR`, `TAMQ_SOCKET`, and `TAMQ_POLICY_PROFILE` may
|
||||
override these defaults. The CLI MUST provide tab completion through
|
||||
`tamq completion bash|zsh|fish` and expose completion for subcommands,
|
||||
options, and known gita repository targets.
|
||||
|
||||
Version 0.1 supports direct addressing only. Unknown or unregistered targets
|
||||
are rejected; there is no broadcast or wildcard routing. If a target session is
|
||||
absent, `tmux-amq` opens it and starts the configured command. The sender label
|
||||
in the injected form is derived from the authenticated source repository, not
|
||||
from message text.
|
||||
|
||||
Delivery acknowledgment is configurable and defaults to `injected`, meaning the
|
||||
message is considered delivered once tmux-amq successfully writes it to the
|
||||
target PTY. An optional `acknowledged` mode retains the message until the target
|
||||
agent explicitly confirms receipt; retries use the same message ID. This
|
||||
facility carries coordination messages, not task/workplan state. Substantive
|
||||
work, dependencies, and completion remain represented by State Hub facilities.
|
||||
|
||||
Message bodies are human-readable UTF-8 plain text, limited to 8 KiB and
|
||||
preserving multiline content. The transport envelope carries structured IDs,
|
||||
sender/target slugs, timestamps, and policy metadata. Binary payloads and
|
||||
oversized bodies are rejected. Message text is never interpreted as task or
|
||||
workplan state.
|
||||
|
||||
On attach, `tmux-amq` connects to a coordination-engine Unix domain socket and
|
||||
performs a handshake, receiving a unique
|
||||
`coordination_endpoint_id`. That identifier namespaces all messages and leases
|
||||
originating from the connected endpoint, so local IDs can safely be reused
|
||||
across different machines or sessions without cross-endpoint collision.
|
||||
Coordination-engine MUST treat `(coordination_endpoint_id, local_message_id)`
|
||||
as the message identity and preserve the endpoint ID in receipts.
|
||||
|
||||
The socket protocol MUST use structured messages and authenticate the peer by
|
||||
filesystem ownership/permissions. The default deployment runs both processes
|
||||
under the same approved local user, uses socket mode `0600`, and validates Unix
|
||||
peer credentials; bearer tokens in command lines are not required. The initial
|
||||
handshake includes the gita
|
||||
registered repository slugs, tmux session name, and agent command; the response
|
||||
contains the endpoint ID and negotiated lease/receipt capabilities. No TCP
|
||||
listener is required for the local integration.
|
||||
|
||||
coordination-engine MUST refresh the local gita registry before accepting an
|
||||
attach or addressing a target. It accepts only exact registered repository
|
||||
slugs, requires the attached session to report the matching slug/path, and
|
||||
never auto-clones or auto-registers a repository.
|
||||
|
||||
The adapter interface is:
|
||||
|
||||
```yaml
|
||||
WakeRequest:
|
||||
lease_id: string
|
||||
target_repo: string # must be gita-registered and an active tmux-amq target
|
||||
target_agent: string?
|
||||
trigger: WorkerTrigger
|
||||
checkpoint: Checkpoint?
|
||||
prompt: string
|
||||
|
||||
WakeAck:
|
||||
lease_id: string
|
||||
session_id: string
|
||||
accepted_at: timestamp
|
||||
capability: resumed | started | unavailable
|
||||
```
|
||||
|
||||
The prompt is generated from the trigger and the standard continuation policy;
|
||||
it MUST contain no secret values. The target agent remains the authority for
|
||||
editing files, calling tools, and updating State Hub.
|
||||
|
||||
## 6. Checkpoints and standard continuation policy
|
||||
|
||||
Agents SHOULD publish a checkpoint before yielding or stopping:
|
||||
|
||||
```yaml
|
||||
Checkpoint:
|
||||
lease_id: string
|
||||
task_id: string?
|
||||
summary: string
|
||||
files_changed: [string]
|
||||
next_action: string?
|
||||
blocked_reason: human | secret | destructive | policy | dependency | unavailable | null
|
||||
recorded_at: timestamp
|
||||
```
|
||||
|
||||
When a lease is resumed, the service supplies the latest checkpoint and asks
|
||||
the agent to continue. The following policy templates are recognized, in order:
|
||||
|
||||
1. inspect open work and implement the highest-priority actionable item;
|
||||
2. if no work is open, reconcile `SCOPE.md` with `INTENT.md`, record gaps under
|
||||
`history/`, and create/register a workplan for the most relevant gap;
|
||||
3. review pending work, refine it where needed, and implement the next safe item;
|
||||
4. if no safe work remains, close the session and write a perspective entry to
|
||||
the configured `hall-of-helix` destination.
|
||||
|
||||
Templates are suggestions, not permission to bypass safety gates or invent
|
||||
scope. A repository may override them through its agent instructions.
|
||||
|
||||
### 6.1 Policy profiles
|
||||
|
||||
Automatic behavior is selected through named policy profiles rather than code
|
||||
changes. The default profile is conservative:
|
||||
|
||||
```yaml
|
||||
policy:
|
||||
profile: default
|
||||
profiles:
|
||||
default:
|
||||
allow: [statehub_read, repo_inspect, repo_edit, local_checks,
|
||||
state_updates, coordination_messages, tmux_wake, transient_retry]
|
||||
require_human: [secrets, destructive, live_external, scope_change,
|
||||
ambiguous_ownership, external_publish, financial, legal]
|
||||
safety_gated_max_attempts: 0
|
||||
```
|
||||
|
||||
Profiles MUST be selected by configuration, validated at startup, and included
|
||||
by name/version in every lease and receipt. A profile cannot grant access to
|
||||
credentials that are unavailable through the configured credential-routing
|
||||
system, and every profile remains subject to authentication and repository
|
||||
boundary checks.
|
||||
|
||||
## 7. Receipts and observability
|
||||
|
||||
Every trigger, lease transition, wake attempt, checkpoint, stop, retry, and
|
||||
completion MUST emit a sanitized progress/audit receipt containing identifiers,
|
||||
status, reason, timestamps, and retry metadata. Receipts MUST exclude prompt
|
||||
secrets, credentials, payload contents, and unrestricted terminal output.
|
||||
|
||||
The service SHOULD publish receipts through State Hub progress/events and retain
|
||||
enough correlation data to explain why a dependent task was (or was not) woken.
|
||||
|
||||
## 8. Ownership boundary
|
||||
|
||||
Repositories publish workplan/task/message state and consume wake requests. They
|
||||
MUST NOT add independent polling daemons for this feature. Coordination-engine
|
||||
owns the service process, observation, lease/deduplication, retry policy, and
|
||||
wake dispatch. State Hub owns durable task/message state. Terminal/session
|
||||
control is a pluggable adapter owned by coordination-engine and deployed with
|
||||
the runtime; its underlying bridge remains an external dependency.
|
||||
|
||||
## 9. Operator decisions required before implementation
|
||||
|
||||
The following choices cannot be inferred safely from repository documents:
|
||||
|
||||
1. Which terminal/session bridge is authorized to wake or resume workers?
|
||||
2. What local SQLite retention and backup policy should be used for leases and
|
||||
receipts?
|
||||
3. Default polling interval, lease duration, renewal interval, and retry limit?
|
||||
4. Which actions are pre-approved policies versus always human-gated?
|
||||
5. What service identity and authentication path may write State Hub and invoke
|
||||
the wake adapter?
|
||||
6. Which Unix socket path and filesystem ownership should the local deployment
|
||||
use?
|
||||
|
||||
### 9.1 Runtime configuration
|
||||
|
||||
The following values MUST be configurable without code changes:
|
||||
|
||||
```yaml
|
||||
coordination:
|
||||
statehub_poll_interval_seconds: 15
|
||||
wake_ack_timeout_seconds: 30
|
||||
lease_renew_interval_seconds: 10
|
||||
retry_backoff_seconds: [5, 15, 60, 300]
|
||||
max_attempts: 4
|
||||
safety_gated_max_attempts: 0
|
||||
delivery_ack_mode: injected # injected | acknowledged
|
||||
```
|
||||
|
||||
Deployments may choose different values, including up to nine attempts. The
|
||||
service MUST validate `max_attempts` and `safety_gated_max_attempts` in the
|
||||
range 0..9 and record the effective configuration version in receipts.
|
||||
|
||||
State Hub observation uses the configured polling interval (15 seconds by
|
||||
default), backs off exponentially while unavailable, and resumes promptly when
|
||||
connectivity returns. Local tmux-amq messaging is never blocked by State Hub
|
||||
outages; receipt projections are queued for asynchronous publication.
|
||||
|
||||
The State Hub endpoint is configurable through `STATEHUB_API_BASE` or
|
||||
`statehub.api_base`, defaulting to `http://127.0.0.1:8000`. Credentials MUST be
|
||||
resolved through the approved credential-routing mechanism and never stored in
|
||||
tamq configuration, SQLite, JSONL exports, tmux commands, or receipts. Missing
|
||||
credentials leave local messaging operational while State Hub projections stay
|
||||
pending.
|
||||
|
||||
`tamq status` exposes live endpoint/session, queue, lease, and State Hub
|
||||
connectivity information. `tamq history` exposes full local delivery history;
|
||||
State Hub receives sanitized receipts and correlation IDs only. Message bodies
|
||||
remain local unless explicitly exported to JSONL.
|
||||
|
||||
History is never deleted automatically. When invoked without explicit filters,
|
||||
`tamq purge` uses dynamic defaults equivalent to `--before 365d` and
|
||||
`--max-size 100MB`; purge requires confirmation and may be preceded by JSONL
|
||||
export. On startup, if history exceeds 100 MB, tamq prints an advisory such as:
|
||||
`Size of history is NNN MB since YYMMDD, exceeding 100MB. Consider using 'tamq purge'.`
|
||||
|
||||
`tamq purge` performs a dry-run summary by default, reporting the matching
|
||||
message count, date range, and estimated bytes. Interactive execution requires
|
||||
explicit confirmation; non-interactive execution requires `--yes`. Combined
|
||||
filters are allowed, and each purge emits a receipt containing filters and
|
||||
counts without message bodies.
|
||||
|
||||
`tamq start` creates or reuses the tmux server/windows and starts the local
|
||||
service; `tamq serve` runs the Unix-socket service in the foreground; `tamq stop`
|
||||
stops the service without killing worker terminals or deleting queues. The
|
||||
initial repo-opening command MUST ensure the service is alive and start it
|
||||
automatically when absent. Startup is idempotent and lock-protected so two
|
||||
concurrent repo opens cannot create duplicate services. `--detach` is required
|
||||
to daemonize; foreground operation is the default for diagnostics.
|
||||
|
||||
If automatic startup fails, tamq reports the error on stderr, returns non-zero,
|
||||
does not register an endpoint or claim delivery, and leaves existing sessions
|
||||
and SQLite data untouched. `--no-service` may explicitly open terminals without
|
||||
messaging, with a visible warning.
|
||||
|
||||
## 10. Logging and diagnostics
|
||||
|
||||
Foreground `tamq serve` logs to stderr. Detached operation logs to
|
||||
`${XDG_STATE_HOME:-$HOME/.local/state}/tamq/tamq.log`. The default level is
|
||||
`info`; `--quiet` suppresses non-errors, `--verbose` enables debug diagnostics,
|
||||
and `--json` requests structured output where applicable. Message bodies,
|
||||
credentials, tokens, and unrestricted PTY output are omitted by default.
|
||||
|
||||
`--orwell` is an explicitly unsafe, non-production diagnostic mode that logs
|
||||
otherwise-omitted diagnostic fields, including message bodies and credential
|
||||
material when available. It MUST be supplied per invocation, emit a prominent
|
||||
warning, write only to a local mode-`0600` sink, never project to State Hub, and
|
||||
be rejected by the default production policy profile. Operators are responsible
|
||||
for purging Orwell logs after diagnosis.
|
||||
|
||||
This practice is proposed for canonization as the InfoTechCanon PracticePattern
|
||||
`practice-pattern/orwell-logging-diagnostics` (`OrwellLoggingDiagnostics`). The
|
||||
canonical owner is info-tech-canon; tamq is a concrete known use, not the owner
|
||||
of the general practice.
|
||||
|
||||
The first runtime implementation uses Python 3.11+ and should prefer standard
|
||||
library components (`sqlite3`, `asyncio`, Unix sockets, and CLI primitives) so
|
||||
local installation remains small and reliable.
|
||||
|
||||
The project is packaged through a root `pyproject.toml` with a `tamq` console
|
||||
entry point. It must support `uv tool install .`, editable development installs,
|
||||
and package-derived `tamq --version` output.
|
||||
|
||||
Verification uses layered tests: pytest unit tests for state/config/protocol
|
||||
logic; Unix-socket integration tests with fake tmux-amq peers; fake State Hub
|
||||
and gita registry tests; CLI behavior tests; and opt-in live smoke tests only
|
||||
when explicitly configured. Tests must not require credentials or mutate live
|
||||
systems.
|
||||
|
||||
The Unix-socket protocol is versioned independently from package versions,
|
||||
starting at `0.1`. Attach handshakes negotiate protocol version and capabilities;
|
||||
incompatible major versions are rejected, compatible minor versions may
|
||||
interoperate, and the negotiated values are retained in endpoint/receipt data.
|
||||
|
||||
SQLite stores an explicit schema version. Startup applies forward migrations in
|
||||
transactions, creates a timestamped backup before altering message/lease
|
||||
tables, and refuses to run against a newer schema. Message history is never
|
||||
silently dropped; `tamq db-version` reports the current schema.
|
||||
|
||||
SQLite uses WAL mode, foreign-key enforcement, and a configurable busy timeout
|
||||
(5 seconds by default). Queue and lease transitions are transactional, with a
|
||||
single coordination-engine writer path and concurrent readers. Transient busy
|
||||
errors may retry without creating duplicate messages.
|
||||
|
||||
On `SIGTERM` or `SIGINT`, the service stops accepting socket requests and new
|
||||
leases, finishes the current transaction, marks the endpoint disconnected,
|
||||
closes the socket, preserves queues/leases for recovery, emits a sanitized
|
||||
shutdown receipt, and exits within a configurable grace period (10 seconds by
|
||||
default).
|
||||
|
||||
Default CI gates are `uv run pytest`, `git diff --check`,
|
||||
`python -m compileall src`, `tamq --help`, and `tamq --version`; package
|
||||
install/build and live smoke checks are separate opt-in jobs.
|
||||
|
||||
Health is local-only: `tamq status` is human-readable, `tamq status --json` is
|
||||
machine-readable, and `tamq ping` performs a lightweight Unix-socket liveness
|
||||
check. Status separates process/socket, SQLite, gita registry, State Hub, queue,
|
||||
and lease health; no TCP health port is exposed.
|
||||
103
workplans/COORDINATION-WP-0003-worker-coordination-service.md
Normal file
103
workplans/COORDINATION-WP-0003-worker-coordination-service.md
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
---
|
||||
id: COORDINATION-WP-0003
|
||||
type: workplan
|
||||
title: "Worker coordination service contract"
|
||||
domain: communication
|
||||
repo: coordination-engine
|
||||
status: ready
|
||||
owner: codex
|
||||
topic_slug: communication
|
||||
created: "2026-08-23"
|
||||
updated: "2026-08-23"
|
||||
---
|
||||
|
||||
# Worker coordination service contract
|
||||
|
||||
Define and implement the cross-repository worker wake-up and
|
||||
dependency-coordination capability requested by net-kingdom. Coordination-engine
|
||||
owns the protocol and runtime. State Hub and the separate `tmux-amq` local tmux
|
||||
message queue are adapters. Only gita-registered repos are valid worker targets.
|
||||
|
||||
## Publish the v0.1 contract
|
||||
|
||||
```task
|
||||
id: COORDINATION-WP-0003-T01
|
||||
status: done
|
||||
priority: high
|
||||
```
|
||||
|
||||
Authored `spec/worker-coordination-service-v0.1.md`, covering State Hub
|
||||
observation, actionability gates, leases, deduplication, wake requests,
|
||||
checkpoints, retries, safety stops, receipts, and operator decisions.
|
||||
|
||||
## Agree adapter and deployment decisions
|
||||
|
||||
```task
|
||||
id: COORDINATION-WP-0003-T02
|
||||
status: wait
|
||||
priority: high
|
||||
```
|
||||
|
||||
The local transport is a Unix domain socket. Coordination-engine uses local
|
||||
SQLite for coordination leases, deduplication, and receipts, projecting
|
||||
sanitized state to State Hub. Net-kingdom/operator must choose the socket
|
||||
path (same-user mode `0600` by default), `tmux-amq` handshake fields, SQLite
|
||||
retention/backup policy, timers/retry defaults, the configured policy profile,
|
||||
and strict gita registry validation. Policy profiles define the allowed and
|
||||
human-gated action classes. v0.1 uses direct-only routing; broadcast is deferred.
|
||||
Delivery acknowledgment is configurable and defaults to `injected`; this layer
|
||||
does not duplicate State Hub task/workplan state.
|
||||
Message bodies are UTF-8 plain text with an 8 KiB limit and structured metadata
|
||||
kept in the transport envelope.
|
||||
Endpoint identity is `tmux-amq-<tmux-server-PID>`; each endpoint has at most one
|
||||
tmux window per gita repository.
|
||||
tmux-amq must support local history inspection, export to a messages file, and
|
||||
safe replay of that file through normal routing and policy checks.
|
||||
History is retained by default; explicit `tamq purge` uses `--before 365d` and
|
||||
`--max-size 100MB` defaults, with a startup advisory when history exceeds 100MB.
|
||||
The service uses `tamq start`/`serve`/`stop`; first repo opening auto-starts an
|
||||
absent service with an idempotent lock-protected check.
|
||||
Logging defaults to safe stderr/file output; `--orwell` is an explicit,
|
||||
non-production, local-only mode for otherwise-omitted sensitive diagnostics.
|
||||
|
||||
## Establish OrwellLoggingDiagnostics practice pattern
|
||||
|
||||
```task
|
||||
id: COORDINATION-WP-0003-T04
|
||||
status: wait
|
||||
priority: medium
|
||||
```
|
||||
|
||||
Requested candidate canon artifact `practice-pattern/orwell-logging-diagnostics`
|
||||
from info-tech-canon, with tamq as the first known use. Await canonical owner
|
||||
review and registration.
|
||||
|
||||
The first runtime implementation is Python 3.11+ with standard-library-first
|
||||
dependencies.
|
||||
Package through root `pyproject.toml` with a `tamq` console entry point and uv
|
||||
install/editable-install support.
|
||||
Verification uses pytest unit, fake-peer integration, CLI, and opt-in live
|
||||
smoke tests without production credentials.
|
||||
Default CI gates: `uv run pytest`, `git diff --check`, compileall, and tamq
|
||||
help/version checks; package and live smoke checks remain opt-in.
|
||||
The executable name is `tamq`, with Unix-standard `--help`/`-h` and
|
||||
`--version`/`-V` flags.
|
||||
Use XDG config/state/runtime paths with environment overrides and provide
|
||||
`tamq completion bash|zsh|fish` for tab expansion.
|
||||
`tmux-amq` independently owns its durable queue and local delivery leases.
|
||||
Lease/retry timing and attempt counts are configuration parameters; the retry
|
||||
ceiling is 9, while safety-gated retries default to 0 and require explicit
|
||||
policy. Runtime ownership is coordination-engine;
|
||||
tmux/session ownership is `tmux-amq`.
|
||||
|
||||
## Implement the coordination runtime
|
||||
|
||||
```task
|
||||
id: COORDINATION-WP-0003-T03
|
||||
status: wait
|
||||
priority: high
|
||||
```
|
||||
|
||||
Deferred while `tmux-amq` is bootstrapped as the standalone local queue and
|
||||
tmux control-mode endpoint. Coordination-engine integration will follow the
|
||||
stable tamq Unix-socket protocol.
|
||||
Loading…
Add table
Add a link
Reference in a new issue