← Files NaClARCHIVED FILE

skills/nacl-sa/resources/workflows/nacl-sa-architect/SKILL.md

16.1 KB · Oct 5, 2026 · 18:29 UTC

↓ Download file

---
name: nacl-sa-architect
description: |
  Decompose a NaCl system into modules, context-map dependencies, and NFRs in
  the SA graph. Use when the user asks to design architecture, define bounded
  contexts, add a module, create a system overview, or says `/nacl-sa-architect`.
---

# NaCl SA Architect For Codex

Perform graph-first architectural decomposition for the SA layer. User-facing SA
artifacts are Russian by default unless the user explicitly requests another
supported language.

Read `../nacl-core/SKILL.md`, `../references/migration-rules.md`, and
`../references/verification-vocabulary.md` before using this workflow.

## Workflow

Use `full` for an initial decomposition and `module` for adding one module to an
existing architecture.

1. Pre-flight: check available graph tooling, read `config.yaml` when available,
   inspect `Module` coverage, and verify whether BA nodes exist.
2. Import BA context: read `ProcessGroup`, `BusinessProcess`, automated
   `WorkflowStep`, `BusinessEntity`, `BusinessRole`, and `BusinessRule` data.
3. Business context: summarize goals, scope, success criteria, and assumptions
   in Russian; ask the user to confirm before continuing.
4. Module decomposition: propose `Module` nodes, UC ranges, ownership of domain
   entities, and `ProcessGroup` to `Module` handoff edges. Stop for explicit
   confirmation before graph writes.
5. Context map: propose inter-module `DEPENDS_ON` relationships with dependency
   type and rationale. Stop for explicit confirmation before graph writes.
6. **External Contracts** (between Context Map and NFR): enumerate every
   external provider and every wire-protocol the system depends on; create one
   `.tl/external-contracts/<slug>.md` artifact per provider AND per protocol;
   then create `ExternalContract` graph nodes and `DEPENDS_ON_EXTERNAL` /
   `REQUIRES_EXTERNAL` edges. Stop for explicit confirmation before writing
   any artifact or graph node. See **External Contracts Phase** below for the
   required field list and worked examples (kie.ai, TUS).
7. NFRs and constraints: propose `Requirement` nodes for NFRs, assumptions, and
   architecture decisions; connect them to modules when applicable. Stop for
   explicit confirmation before graph writes. NFRs (`type='nfr'`) are exempt from
   the `REALIZED_BY` implementer-anchor gate (validator L3.7) by design — they stay
   free-floating or Module-linked; do not anchor them to steps/fields/forms.
8. Verification: read back modules, dependencies, external contracts, NFRs, and
   BA handoff coverage. Report with the closed verification vocabulary.

When BA data is incomplete, state the gap, propose clearly marked assumptions,
and create assumption requirements only after user confirmation.

## External Contracts Phase

This phase sits between Context Map (step 5) and NFRs (step 7). It exists
because postmortems of two NaCl projects identified ~13 distinct sites where
the codebase compiled, TS types aligned, but the live wire to an external
provider or protocol failed. Examples include the kie.ai endpoint shape
(Anthropic envelope, async polling, model namespace without `google/`
prefix), the TUS upload protocol (`Location` header public-origin behind
Caddy, Fastify `addContentTypeParser` for `application/offset+octet-stream`,
canonical `mime_type` metadata key), the SSE frame envelope (`event:
<type>\ndata: <json>` lines), reverse-proxy URL scheme translation, and the
ffmpeg/ffprobe runtime URL-scheme acceptance set. See
`docs/retrospectives/project-beta-runtime-baseline.md` §§ A1–A9 and B1–B7
for the full catalog.

### Artifact

One Markdown file per provider AND one per protocol:

```
.tl/external-contracts/<slug>.md
```

Filenames are slug-form: `kie.md`, `deepgram.md`, `anthropic.md` (providers);
`tus.md`, `sse.md`, `multipart-presigned.md`, `reverse-proxy-url-scheme.md`,
`ffmpeg-ffprobe-runtime.md` (protocols). The canonical template lives at
`.tl/external-contracts/_template.md`.

### Required fields (per file)

1. **Identity.** Name; `kind: provider | protocol`; created / updated dates;
   references to TECH-### / UC-### in the graph.
2. **Endpoint.** Full URL **including** version-path (do not record "base
   host" alone if the adapter appends `/api/v1`); every called endpoint with
   method + path + purpose; discovery mechanism (`static-catalog` or
   `http-list-endpoint`); versioning strategy.
3. **Auth.** Scheme (`Bearer`, `x-api-key`, `none`, ...); secret env-var
   name; missing-secret behavior — what `nacl-tl-qa` does when the secret
   is absent (pre-provider stages still run; provider stage marks
   `NOT_RUN`; never silent SKIP).
4. **Request shape.** Content-Type; required headers; body with **literal**
   field names (not "matches the TS type" — write the literal strings; the
   project-beta TUS three-way collision `mime_type` vs `filetype` was a
   prose/Zod/table mismatch on a literal field name); query params.
5. **Response shape.** Success status; body with literal field names; the
   exact accessor chain to extract the load-bearing value (e.g. for
   kie.ai's Anthropic shape: `response.content[0].text`, not
   `response.choices[0].message.content`); required response headers
   (`Location`, `Tus-Resumable`, ...).
6. **Lifecycle: sync vs async.** Explicitly mark `sync` or `async`. If
   async: submit endpoint, poll endpoint, polling cadence (min/max
   interval, backoff), polling timeout (must surface FAILED, never silent
   hang), cancellation. (The kie.ai image_gen episode flipped sync to
   async mid-build.)
7. **File URL reachability.** When the contract returns or consumes a URL:
   expected scheme (`https://` for browser-facing; `s3://` rejected by
   ffprobe); who sets `X-Forwarded-Proto`; is `respectForwardedHeaders`
   enabled; public origin vs origin server (`Location` returned to browser
   must be the public origin); URL TTL; toolchain compatibility.
8. **Failure codes.** Enumerate the HTTP codes the consumer handles, what
   each means, and the required consumer action. Minimum rows: `4xx auth`,
   `4xx model/endpoint`, `4xx envelope`, `429 rate-limit`, `5xx transient`.
9. **Model namespace / catalog** (required when `kind == provider`).
   Catalog source (`static-list-in-this-file` or `http-list-endpoint`);
   namespace prefix policy (`NONE` / `<vendor>/` / `<vendor>:` — be exact;
   the Project-Alpha nano-banana episode regressed when the adapter prefixed
   `google/`); list of models used verbatim.
10. **Fixture-test path.** Repo-relative path to a runnable test that
    loads a recorded response fixture and parses it through the production
    code path without mocking the parse step. This file is what
    `nacl-tl-sync`'s Wire-Evidence Gate (W2) recognises as
    `wire-evidence:fixture:<path>`.
11. **Smoke-test path.** Repo-relative path to a runnable smoke test that
    hits the real provider/protocol surface in a sandbox or staging
    environment. May require network access and env vars; must be runnable
    on demand by `nacl-tl-qa` per the Stage Decomposition Gate.

### Optional fields

Include only when the integration uses the surface: webhook callback shape;
SSE/stream frame envelope; multi-tenant routing header; idempotency-key
header; pagination shape; concurrency/per-key rate limits; region pinning;
vendor SDK version pin; framework-specific gotchas (Fastify, Caddy,
ffmpeg). Full optional list in `.tl/external-contracts/_template.md`.

### Worked example 1 — kie.ai (provider)

```
File: .tl/external-contracts/kie.md
Kind: provider
Endpoint:
  Base URL:    https://kie-ai.redpandaai.co
  All endpoints:
    POST /api/v1/jobs/createTask     - async image generation
    GET  /api/v1/jobs/recordInfo     - poll task status
    POST /api/v1/messages            - Anthropic-shape LLM call (sync)
  Discovery:   static-catalog
  Versioning:  path segment /api/v1 (pinned 2026-05-19)

Auth:
  Scheme:      x-api-key
  Env var:     KIE_API_KEY
  Missing:     nacl-tl-qa decomposes pipeline; pre-provider stages run

Request (Anthropic-shape):
  Headers:     x-api-key, anthropic-version: 2023-06-01
  Body:        { model, max_tokens, messages: [{role, content}] }

Response (Anthropic-shape):
  Status:      200
  Body:        { id, type, role, model, content: [{type, text}] }
  Accessor:    response.content[0].text
               (NOT response.choices[0].message.content)

Lifecycle:
  LLM:         sync
  image_gen:   async: createTask -> recordInfo poll (2s/1.5x/cap 30s/5min)

File URL reachability: N/A (no file URLs in/out)

Failure codes:
  401 auth          -> AUTH_FAILED
  404 model         -> MODEL_NOT_FOUND
  400 envelope      -> CONTRACT_FAILED
  429 rate-limit    -> backoff 2/4/8s
  5xx transient     -> backoff, budget 5 retries

Model namespace:
  Catalog:           http-list at GET /api/v1/models
  Prefix policy:     NONE (verbatim model ids; NO "google/" prefix)
  Models:            claude-3-5-sonnet-20241022, nano-banana-v1

Fixture-test path:   tests/wire/kie-ai.fixture.test.ts
                     (loads tests/fixtures/kie-ai/protocol-response.json)
Smoke-test path:     tests/smoke/kie-ai.smoke.test.ts
                     (env: KIE_API_KEY; stage PROVIDER_QA)
```

### Worked example 2 — TUS upload (protocol)

```
File: .tl/external-contracts/tus.md
Kind: protocol
Endpoint:
  Base URL:    https://<public-origin>/tus  (public origin, not origin server)
  All endpoints:
    POST   /tus       -> 201 + Location: <upload-url-public-origin>
    HEAD   /tus/<id>  -> 200 + Upload-Offset
    PATCH  /tus/<id>  -> 204; Content-Type: application/offset+octet-stream
                         (MUST register via fastify.addContentTypeParser;
                          unregistered -> 415)
  Discovery:   protocol spec https://tus.io/protocols/resumable-upload
  Versioning:  Tus-Resumable: 1.0.0

Auth:
  Scheme:      Bearer (project JWT) on POST + PATCH
  Missing:     returns 401 before storage I/O

Request:
  Content-Type: application/offset+octet-stream (PATCH)
  Headers:
    Upload-Length          (POST)
    Upload-Metadata        (POST) - canonical key: mime_type (NOT filetype)
    Upload-Offset          (PATCH)
    Tus-Resumable: 1.0.0   (all)

Response:
  Status:     201 (POST), 204 (PATCH), 200 (HEAD)
  Headers:
    Location: <https-public-origin>     (POST)
    Tus-Resumable: 1.0.0                (all)
    Upload-Offset                       (PATCH, HEAD)

Lifecycle: sync (chunked PATCH within one resumable session)

File URL reachability:
  Scheme expected:   https:// (browser-facing)
  Proxy:             Caddy sets X-Forwarded-Proto; Fastify trustProxy: true;
                     TUS server consumes Forwarded headers when building
                     Location. Returning http://api-internal:... breaks
                     browser-side resume.
  Public vs origin:  Location MUST be public origin.

Failure codes:
  415 unsupported    -> addContentTypeParser missing
  412 precondition   -> Tus-Resumable mismatch
  409 conflict       -> Upload-Offset mismatch
  410 gone           -> session reaped; retry from POST
  413 too large      -> chunk above Upload-Length

Model namespace: N/A (protocol)

Fixture-test path:   tests/wire/tus.fixture.test.ts
Smoke-test path:     tests/smoke/tus-upload.smoke.test.ts
                     (env: PUBLIC_BASE_URL=https://...; stage WIRE_CONTRACT_QA)
```

### Graph writes

The pilot gateway has no `ExternalContract` resource or relationship mutation.
After producing the confirmed file artifact, report
`Status: BLOCKED` with code `SA_RELATIONSHIP_RESOURCE_UNAVAILABLE` for graph
materialization. Do not execute inline graph statements or repurpose a
`Module`, `FeatureRequest`, or `UseCase` scalar mutation. A later package must
add a named, policy-controlled capability before this step can complete.

### Relationship to downstream skills

- `nacl-tl-plan` (W6 consumer-side): emits `Status: BLOCKED` workflow detail
  `external-contract-missing` when a task references a provider/protocol
  whose `.tl/external-contracts/<slug>.md` is absent. Override via signed
  exception only (W4 schema).
- `nacl-tl-sync` (W2 Wire-Evidence Gate): consumes field 10 (fixture-test
  path) as `wire-evidence:fixture:<path>` and field 11 (smoke-test path) as
  `wire-evidence:contract-test:<path>` / `wire-evidence:live-smoke:<ts>`.
  Without these, sync downgrades to `Status: UNVERIFIED workflow-detail
  wire-evidence-missing`.
- `nacl-tl-qa` (W3 Stage Decomposition Gate): consumes field 3
  (missing-secret behavior) and field 11 (stage decomposition tag) to keep
  pre-provider stages testable when a provider key is unavailable.

### Override

The only override is a signed exception under the W4 schema. There is no
inline `--skip-external-contract` flag and none will be introduced.

## Graph Contract

Pre-flight must check `graph-infra/schema/sa-schema.cypher` and the relevant
query files when readable. If graph tools are unavailable, stop before
persistence and return a graph-ready change plan with `Status: BLOCKED`.

Canonical writes are limited to `Module`, architectural `Requirement` records,
`ExternalContract` (with `kind: provider | protocol` and a `file_path`
pointing at the corresponding `.tl/external-contracts/<slug>.md`),
`ProcessGroup -[:SUGGESTS]-> Module`, `Module -[:DEPENDS_ON]-> Module`,
`Module -[:DEPENDS_ON_EXTERNAL]-> ExternalContract`,
`UseCase -[:REQUIRES_EXTERNAL]-> ExternalContract`, and ownership
relationships supported by the schema such as `CONTAINS_UC` and
`CONTAINS_ENTITY`. Do not introduce unsupported architecture labels or
relationships.

Before each write batch, show candidate module ids, names, UC ranges, bounded
context rationale, dependency direction, dependency type, NFR text, and BA
source evidence. After confirmed writes, read back with `sa_module_overview`,
handoff coverage queries, or equivalent graph reads and report observed counts.

## Capabilities

### May Do

- Read BA and SA graph data when graph tools are available.
- Propose modules, UC ranges, module ownership, dependencies, external
  contracts, NFRs, and assumptions.
- Write `Module`, `Requirement`, `ExternalContract`, `SUGGESTS`,
  `DEPENDS_ON`, `DEPENDS_ON_EXTERNAL`, `REQUIRES_EXTERNAL`, and related
  ownership edges after explicit confirmation.
- Write `.tl/external-contracts/<slug>.md` artifacts after explicit
  confirmation. One file per provider AND one per protocol.
- Preserve BA-to-SA traceability from process groups and automated workflow
  scope into SA architecture.

### Must Not Do

- Modify root-level `nacl-*` source folders.
- Write graph data without a user-facing confirmation gate.
- Invent BA facts that are absent from the user request and graph.
- Break BA, SA, and TL artifact boundaries.
- Select or constrain the runtime.

### Conditional Tools And Actions

- Graph reads and writes require available graph tooling.
- Schema checks require readable schema files or graph introspection.
- File reads require workspace access.
- Destructive graph changes require explicit user approval and should normally
  be avoided.

### Blocked Or Unverified Reporting

- Use `BLOCKED` when graph tooling, source BA data, schema access, or
  confirmation is missing.
- Use `PARTIALLY_VERIFIED` when graph writes complete but only some read-back
  checks can run.
- Use `UNVERIFIED` when architecture coverage cannot be checked against graph
  state.

## Source Comparison

- Source Claude skill path: `../../nacl-sa-architect/SKILL.md`

### Preserved Methodology

- Full and single-module architecture workflows.
- Russian SA artifact language by default.
- Graph-first module, context-map, external-contracts, and NFR persistence.
- One `.tl/external-contracts/<slug>.md` file per provider AND per protocol,
  with all required fields filled (worked examples: kie.ai, TUS).
- BA-to-SA handoff from process groups and automation scope.
- Explicit phase gates before moving forward.

### Removed Claude Mechanics

- Runtime routing fields in frontmatter.
- Hard-coded assumptions that specific graph tools always exist.
- Slash-command-only invocation wording.
- Direct active runtime instructions from the source environment.

### Codex Replacement Behavior

- Treat graph and filesystem access as conditional.
- Ask before every graph write and every major phase transition.
- Report outcomes using only the closed verification vocabulary.
- Keep source references as comparison notes, not active runtime constraints.

SHA-256: d7fc65f9be054bce7bba21c78ac734f92509b5b9a7e3ed8da9c457096332566c