Hex deployment matrix — the five pieces, their adapters, and what actually composes
Requested by founder 2026-07-03 ("enumerate which options we have for deploying each piece, then select which combinations can be deployed together"). Companion to his hexagon diagrams (7/2) and [[2026-07-01-caf-ecosystem-map-and-brigade-restructure-read]]. Vocab: a port is the interface; an adapter implements it against a concrete technology. Driving adapters call into a core; driven adapters are called by it.
First, classify the five pieces
| Piece | Hex role |
|---|---|
| Steward Agent | A core (hexagon) — drives the rail port, drives the cellar port |
| Agent Brigade | A core (hexagon) — driven by the rail port (pulls tickets), drives the cellar port; public surface = the five standard commands (BRIGADE-INTERFACE.md, PR #9) |
| Cellar | A port + a driven adapter behind it (store of knowledge + artifacts) |
| Rail | A port + a driven adapter behind it (mutable ticket queue w/ lease/ack) |
| Use Case Website | A driving consumer on the manifest slice of the cellar port (reads landed Build Manifests; never writes) |
The founder's 7/2 diagram insight holds: cellar (cold) and rail (hot) sit center-touching — in v1 they are literally the same filesystem. In deployment terms that's a co-location choice, not a requirement: they are separate ports and can bind to different adapters, at the cost noted in rule R2.
Packaging vs runtime (founder refinement, 7/3)
The two agents (Steward Agent, Brigade Agent — doc convention per founder 7/3: call them agents; technically they're packaged artifacts, skills shipped in a plugin) don't "deploy" the way the stores do — deploying an agent means installing it into a runtime. That splits what the first draft called "Brigade runtime" into two independent axes:
| Axis | Options |
|---|---|
| Packaging (how the code ships) | Claude Code plugin (LIVE — skill-agent-brigade) · Cowork org-admin-published skills (the 6/15 second rail) · Snowflake Cortex Code — ⚠️ unevaluated: CoCo is real as a runtime (Gary built the KB4 demo in it) but skills/plugin packaging support is unverified — do not assume |
| Runtime (where an installed core executes) | local Code session · headless claude -p cron · Anthropic cloud scheduled sessions · SPCS container · Cowork |
Two consequences:
- Steward and Brigade need not share a runtime. That is the rail boundary doing its job: FOH can live in Cowork (where the 60 sales seats are) while the brigade runs headless on a box or in SPCS. The only shared infrastructure is the two ports — rail + cellar. "Same setting" is a convenience of P0/P1, not a property of the architecture.
- One plugin can package both cores and be installed asymmetrically — same artifact, different seats. The install-set per runtime is a deployment choice (steward skills only, brigade only, or both), not a packaging fork.
So the profile table's Runtime column reads as "runtime(s) the cores are installed into," and P2-P4 are exactly the profiles where steward and brigade runtimes diverge.
Adapter options per piece
Cellar (driven)
| Adapter | Status | Notes |
|---|---|---|
| Local filesystem | LIVE (v1, ~/Projects/phdata-private/cellar/) |
The current everything |
| Git repo (filesystem + remote) | trivial delta | Same fs adapter + push; adds history/multi-machine sync; merge model unsolved for concurrent writers |
| Snowflake stage | documented in CELLAR-SPEC/RAIL-SPEC, not built | Governed, client-data-gravity; supersedes-chain walk needs LIST + GET porting |
| Snowflake Cortex Search | documented, not built | Search-over-cellar, not the store of record — pairs WITH a stage, doesn't replace it |
| S3 / R2 object store | not built; chain-walk port specified in frontend MARKETPLACE.md | Needed the moment any serverless/edge runtime must read the cellar |
Rail (driven)
| Adapter | Status | Notes |
|---|---|---|
| Filesystem dir | LIVE (v1) | Advisory lease — one walker by convention (RAIL-SPEC is honest about this) |
| Snowflake table | designed in RAIL-SPEC, not built | Real atomicity (compare-and-set lease); the client-governed choice |
| Jira / Linear | not built — founder's 7/2 question, deferred then; it belongs here | Viable: ticket=issue, lease=assignee+status transition, work-log=comments (append-only ✓), payload=description+attachments. Challenges: markdown fidelity, attachment size caps for context snapshots, webhook-vs-poll, and Gate A needs API-side field mapping. Big win: the org already lives there — steward intake for the sales backlog could BE a Jira intake form |
| SQS-class queue | not built | Real queue semantics but tickets are mutable documents, not messages — would still need a document store beside it; probably wrong fit alone |
Brigade runtime (where the cores execute)
| Adapter | Status | Notes |
|---|---|---|
| Local Claude Code session (interactive) | LIVE — every run so far | mini or phData laptop |
Headless claude -p + cron/LaunchAgent |
LIVE pattern (RDCO cron suite) | service mode's natural home; needs shared-credential refresh discipline (the 6/22 401 outage lesson) |
| Anthropic cloud scheduled agents | public beta, unevaluated for this | Credential vaults; no local filesystem → forces object-store cellar/rail adapters |
| Snowflake SPCS container | not built | The governed client target; see challenge C1 (egress) |
| Claude Cowork | partially explored (6/15 arch: Cowork-primary for the 60-seat sales org) | Skills rail exists (org-admin published); tool access via remote MCP only → see C2 |
Steward (driving)
| Adapter | Status | Notes |
|---|---|---|
| Interactive Code/Cowork session + steward skill | skill LIVE (steward SKILL.md) | Today's mode; founder-as-requester |
| Structured intake form → ticket | NOT BUILT — the weakest link (step 1 = PARTIAL in the receipts audit) | Required before sales-backlog volume; could be a web form, a Jira intake, or a Slack workflow |
| Slack/Teams bot front-end | not built | Highest-adoption path for 60 sales users; pairs naturally with runner notifications |
Use Case Website (driving consumer) — already enumerated in frontend MARKETPLACE.md
Local dev (cellar adapter, built)
AWS Amplify SSR (needs S3-cellar adapter)
Cloudflare (needs R2-cellar adapter or static export; snowflake-sdk won't run on Workers) SPCS container (built, the original production target)
quick-sites static export (design-noted; needs
generateStaticParams + dropping force-dynamic).
Composition rules (what makes a combo viable)
- R1 — Reachability: the brigade runtime must reach (a) the cellar adapter, (b) the rail adapter, (c) the Anthropic API. Every invalid combo fails one of these three.
- R2 — One-store integrity: cellar and rail may bind to different backends, but artifacts reference each other by path — split backends need a resolver that spans both (PORTS.md seam). Co-locate unless there's a governance reason not to.
- R3 — Auth locality: each runtime has its own secret story (Keychain locally, credential vault in cloud agents, external-access integration + secrets in SPCS, MCP-server-held creds for Cowork). A combo is only viable if every adapter's credential can live in that runtime's story.
- R4 — Concurrency honesty: >1 concurrent
servicewalker requires an atomic-lease rail (Snowflake table or Jira assignee semantics) — the filesystem rail is single-walker by convention.
Named profiles (the combos worth deploying)
Steward and brigade runtimes are specified separately (founder 7/3) — they only share the rail
- cellar ports, never necessarily a machine. Note what the split exposes in P4: the sales seats run the steward in Cowork; the brigade loop is a background process and belongs on a headless runtime, not in an interactive Cowork seat.
| Profile | Steward runtime + intake | Brigade runtime | Cellar | Rail | Website | State |
|---|---|---|---|---|---|---|
| P0 Local dev (today) | local Code session, founder/Ray interactive | same local Code session | filesystem | filesystem | local dev (cellar adapter) | LIVE — the Lenovo run |
| P1 phData single-operator (the #2 port) | interactive Code, phData laptop | same session | filesystem (from zips) | filesystem | local dev | Zips delivered 7/3 — the stress-test profile |
| P2 Team internal | Jira intake form (+ interactive Code) | headless cron on a shared box | git-synced filesystem | Jira/Linear or filesystem+single-walker | Amplify (S3-cellar) | Nearest multi-user step; needs intake + one rail decision |
| P3 Snowflake-native (client-governed) | Cowork / web form | SPCS container | Snowflake stage + Cortex Search | Snowflake table | SPCS (built) | The 321GO/CAF production shape; gated on C1+C2 |
| P4 Cowork sales org | Cowork skill (60 seats) | cloud scheduled sessions or SPCS — a service loop doesn't belong in an interactive seat | Snowflake stage (via remote MCP) | Snowflake table (via remote MCP) | any | Matches 6/15 "Cowork-primary" decision; every port crossing rides ONE remote MCP server |
Per-target technical challenges (the founder's "nuanced" list)
- C1 — SPCS egress (the hurdle he predicted): brigade-in-SPCS must call the Anthropic API → needs an EXTERNAL ACCESS INTEGRATION + network rule + secret object, client-account admin approval. This is org-policy surface area, not just config — some clients will say no, which pushes the brigade runtime OUTSIDE Snowflake (P2) with only cellar/rail inside it. Design consequence: keep runtime↔store coupling loose (already true via the ports).
- C2 — Cowork tool path: Cowork reaches cellar/rail only through a remote MCP server that must be internet-reachable from Anthropic IPs (6/15 decision). That MCP server becomes the single driven-adapter host for P4 — its uptime and authz model are the profile's real risk.
- C3 — Jira/Linear rail fidelity: append-only work-log maps to comments cleanly, but Gate A's deterministic lint needs a field-mapping layer, and big context snapshots hit attachment limits → snapshots stay in the cellar, the Jira ticket carries pointers (which is the contract's intent anyway).
- C4 — Serverless cellar reads: Amplify/Cloudflare websites can't read a laptop filesystem; S3/R2-cellar adapters are specified (chain-walk ports directly) but unbuilt.
- C5 — Secret hygiene per runtime: the no-secrets-on-disk rule (1P/Keychain) has a per-profile translation; P2's shared box and C2's MCP server are the two places it's easiest to get wrong.
- C6 — Cross-machine cellar sync (P1→P0): once the phData machine is live, two cellars exist. Until a shared backend lands, treat ONE as canonical per engagement and move updates as zips/git — do not dual-write.
Recommended sequence
P1 now (zips in hand) → pick P2's rail (Jira vs single-walker filesystem) after the sales-backlog stress test shows real queue shape → build the S3-cellar adapter when the website needs to leave localhost → P3/P4 as the client/GTM motion demands, gated on C1/C2 spikes.
Open questions for founder
- P2 rail: Jira/Linear (org-native, atomic-ish, intake for free) vs stay filesystem single-walker longer? My lean: Jira for the rail + intake, filesystem cellar untouched.
- Is the P4 Cowork profile still the 60-seat target post-re-org (AAI/FDE motion), or does the Tiger Team charter change the consumption surface?
- Which profile does the KB4 onsite (July 15) demo ride on? P1 is safest; P3 is the story the Snowflake AEs want to see.