From arckit
Orchestrates parallel builds of ArcKit artefacts using subagent isolation, dependency DAG, and resumable state.
How this skill is triggered — by the user, by Claude, or both
Slash command
/arckit:arckit-buildThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
You are running the ArcKit build harness. Your job is **orchestration only** — never read or write artefact content yourself. Spawn subagents for that.
You are running the ArcKit build harness. Your job is orchestration only — never read or write artefact content yourself. Spawn subagents for that.
projects/{P}-{NAME}/.arckit/state.json after every wave, before moving on.complete, the file exists at the recorded path, AND every input file's SHA-256 matches the hash recorded at build time, skip. Otherwise the target is stale — rebuild it (and propagate staleness through the DAG). See § "Input-hash change detection".validate-arc-filename.mjs PreToolUse hook is the authoritative path normalizer — it allocates sequence numbers, applies subfolders, pads project IDs at write time. The orchestrator and workers never construct paths by string substitution or call generate-document-id.sh directly. Read the corrected path back from the Write tool result.| Arg | Effect |
|---|---|
<project> | Project directory name or numeric ID (e.g. 001 or 001-arckit-saas). If absent, prompt user. |
--plan | Dry run. Print the wave plan, do not dispatch any Agents, exit. |
--resume | Read state.json; continue from last incomplete wave. |
--target NAME | Build only NAME and its missing dependencies. |
--refresh NAME | Force-rebuild NAME and everything downstream. |
--no-commit | Skip the per-wave git commit. |
--recipe NAME | Recipe name (default uk-saas). Resolved against the precedence list below. |
--enable ID | Enable an optional target (e.g. --enable AIP). |
--exclude ID | Exclude a default-on optional target (e.g. --exclude SVCASS). |
--skip-hash-check | Treat any complete target with its output file present as up-to-date; skip SHA-256 staleness detection. Fast resume; risks missing edits to inputs. |
Recipes are external YAML files. Lookup precedence for --recipe NAME (first hit wins):
.arckit/recipes/{NAME}.yaml — user customizations preserved across plugin updates.${CLAUDE_PLUGIN_ROOT}/skills/arckit-build/recipes/{NAME}.yaml — recipes shipped with the arckit core plugin (uk-saas, uk-mod-sovereign).${CLAUDE_PLUGIN_ROOT}/../arckit-*/recipes/{NAME}.yaml — recipes shipped with installed community plugins (e.g. arckit-uae/recipes/uae-federal-ai.yaml, arckit-ca/recipes/ca-federal-fitaa.yaml).Resolution: glob the parent directory of ${CLAUDE_PLUGIN_ROOT} for arckit-*/recipes/{NAME}.yaml and take the first match. The glob works in both layouts — marketplace-installed plugins land as siblings under the same marketplace-source cache directory, and the dev-mode same-repo layout has them as sibling directories in the repo root.
Default recipe is uk-saas. To customize, copy the core default to .arckit/recipes/uk-saas.yaml and edit there:
mkdir -p .arckit/recipes
cp "${CLAUDE_PLUGIN_ROOT}/skills/arckit-build/recipes/uk-saas.yaml" .arckit/recipes/uk-saas.yaml
Built-in recipes:
| Recipe | Plugin | Use case |
|---|---|---|
uk-saas | arckit (core) | UK Government managed multi-tenant SaaS — civilian departments |
uk-mod-sovereign | arckit (core) | UK MOD / sovereign / air-gapped — mod-secure + jsp-936, no SVCASS, sealed-media distribution |
uae-federal-ai | arckit-uae | UAE Federal AI — full Cabinet agentic AI decree compliance with all 12 UAE community commands, integrated research wave (general AI + AWS / Azure UAE region availability), plus core ArcKit governance |
uae-agentic-transformation | arckit-uae | UAE Federal Agentic AI Transformation — focused 24-month playbook for the 23 April 2026 Cabinet framework's 50%-of-services-by-April-2028 target; ADRs reshaped around agentic architecture (orchestration, human-in-the-loop, observability, kill-switch); PLAN + ROADMAP timeboxed to the 24-month window |
ca-federal-fitaa | arckit-ca | Canadian Federal — FITAA, ITSG-33, GC Digital Standards |
au-federal | arckit-au | Australian Federal / DISP-supplier — ASD Essential Eight, ISM, DTA DSS, Privacy Act 1988, OAIC NDB, PSPF, AI Assurance, DISP attestation (35 targets, 9 waves) |
au-energy | arckit-au-energy (composes arckit-au baseline) | Australian Energy Sector — AESCSF maturity, AER ring-fencing, AEMC NER/NGR, AEMO interfaces, DERMS/DOE, CSIP-AUS layered on the AU federal baseline (Essential Eight, ISM, OT security, SOCI/CIRMP, Privacy Act/NDB). Optional default-off SERVICE_INVENTORY (servicenow). 22 targets. First Australian sector overlay. |
uk-nhs-clinical-safety | arckit (core, references arckit-uk-nhs commands) | UK NHS Clinical Safety + UK/EU MDR — NHS DCB0129 (manufacturer) + DCB0160 (deployer) clinical safety case (Marcus Baw SAFETY.md 3-file spec), NHS DTAC v3, UK MDR 2002 + EU MDR 2017/745 SaMD/AIaMD classification. Composes with UK SaaS baseline (no swaps; adds clinical safety + medical-device regulation on top). 44 targets across 8 waves. First sector overlay. |
See ${CLAUDE_PLUGIN_ROOT}/skills/arckit-build/recipes/uk-saas.yaml for an annotated reference. Top-level keys:
recipe — recipe name (string, must match filename stem)schema_version — recipe schema version (currently 1)description — free textdefaults.version — default version stamp for outputs (e.g. "1.0")optional_targets — map of target ID → {description, default}post_build_hooks — list of {skill, args} to run after final wave (parallel)targets — list of target entriesEach targets[] entry:
| Field | Required | Notes |
|---|---|---|
id | yes | Unique target ID (e.g. PRIN, ADR-001, DIAG-C4) |
skill | yes | ArcKit skill name (e.g. arckit:requirements) |
args | yes | Args string passed to the skill, after substitution |
output.project | yes | "000-global" or "{P}-{NAME}" |
output.type | yes | ArcKit doc-type code (PRIN, REQ, ADR, DIAG, …) — used for state.json keys, NOT for path construction |
output.subfolder | no | Orientation hint shown in --plan and worker prompts; the actual subfolder is enforced by validate-arc-filename.mjs's SUBDIR_MAP at write time |
output.multi_instance | no | Orientation hint; the hook's MULTI_INSTANCE_TYPES list is authoritative |
topic | no | Used in commit messages and {TOPIC} substitution |
deps | yes | List of target IDs, may include glob "ADR-*" |
The output.subfolder / output.multi_instance fields document recipe author intent for human readers and --plan output, but the path-allocation hook is the source of truth at write time. If a recipe says subfolder: decisions for a single-instance type the hook doesn't recognise, the file lands wherever the hook decides — debug via the hook, not the recipe.
The orchestrator substitutes these placeholders in args and output.project before dispatching to workers (workers never see placeholders):
| Placeholder | Source |
|---|---|
{P} | Project ID, zero-padded (e.g. "001") |
{NAME} | Project slug (e.g. "arckit-saas") |
{V} | defaults.version from the recipe |
{TOPIC} | target.topic (multi-instance ADR/DIAG topics) |
deps: ["ADR-*"] matches all targets whose ID begins with ADR-. Exact IDs take precedence; globs expand at wave-computation time against the resolved target list (after optional-target filtering).
The orchestrator records the SHA-256 of every input artefact at build time and compares against the live filesystem on the next run. This catches the "user edited REQ after the build completed but never re-ran" case that pure test -f idempotency misses.
A target's inputs are the resolved output paths of its deps (after glob expansion). Externally-supplied inputs (e.g. external/policies/*.md) are not hashed by v0.4 — only artefacts the harness itself produced or recorded as source: "pre-existing". Recipes that surface external inputs should hash them in v0.5.
Each completed target's state entry gains an input_hashes map of dep-ID → SHA-256:
"RISK": {
"status": "complete",
"path": "projects/001-arckit-saas/ARC-001-RISK-v1.0.md",
"input_hashes": {
"REQ": "9f2a...c41e",
"STKE": "1b88...07ad",
"PRIN": "44e7...bc92"
},
...
}
The map is populated by the orchestrator (Bash sha256sum) immediately after a target validates complete in step 5 — workers don't compute hashes.
--skip-hash-check)At work-list computation (step 7 of the run order):
done = { t ∈ state.targets : t.status == "complete" AND test -f t.path }.t ∈ done, recompute SHA-256 for every entry in t.input_hashes. If any current hash differs from the recorded value (or the input file is now missing), t is stale — move it from done back into pending and clear it from state.targets[t].status (set "stale").--refresh NAME are marked stale unconditionally (existing behaviour — overrides hash check).--skip-hash-check, skip steps 2–3 entirely. done is whatever survives the test -f filter.Print the staleness reason in the --plan output so users can see why a target rebuilt:
Wave 1: REQ
(stale) REQ ← file edited since last build (sha mismatch)
Wave 3: RISK, HLD, STRATEGY, ...
(stale-cascade) RISK ← REQ changed since 2026-05-12T10:14:03Z
SHA-256 of typical ArcKit artefacts (≤500 KB markdown) is sub-millisecond per file. A 50-target project incurs <100 ms of hashing on --resume. Workers do no hashing; only the orchestrator does (single shell loop in step 5/step 7).
Standard topological sort with parallelism:
pending = recipe.targets ∩ enabled - done — where enabled reflects --enable/--exclude flags and optional_targets[id].default, and done is computed by the staleness rules in § "Input-hash change detection" (i.e. complete AND test -f AND every input hash matches, unless --skip-hash-check is set). Stale targets stay in pending.done from staleness computation above.wave = { t ∈ pending : deps(t) ⊆ done } (after expanding globs)Worked example — for project 001 (UK-SaaS recipe) starting from empty state, the algorithm produces something like:
Treat this as illustrative only; the harness recomputes waves at runtime from the recipe DAG.
For each wave, in order:
Print:
Wave {N}/{total}: {targets joined}
- estimated agents: {len(wave)}
- estimated duration: ~2-5 min wall-clock per agent (parallel)
Use the Agent tool with subagent_type: "general-purpose". One Agent call per target. All in the same assistant message so they run in parallel.
Per-agent prompt template (substitute {...} placeholders from the resolved target):
You are an ArcKit artefact worker subagent (orchestrated by arckit-build, wave {WAVE_N}).
Project: {PROJECT_ID} ({PROJECT_NAME})
Target: {TARGET_ID}
Skill to invoke: {SKILL}
Skill args: {ARGS_RESOLVED}
Expected directory: {EXPECTED_DIR} # for orientation only — actual filename is hook-allocated
Inputs you may read (only these):
{INPUT_PATHS_BULLETED}
Steps:
1. Use the Skill tool to invoke `{SKILL}` with the args above verbatim.
**Interactive Q&A handling (CRITICAL — subagents have no user available):**
If the skill calls `AskUserQuestion`, you MUST select the option marked `(Recommended)`
without asking. If no option is marked Recommended, use these defaults:
| Question header | Default |
|-----------------|---------|
| Scope | `Full system` |
| Consultation | `Surveys` |
| Phase | value from skill args, else `alpha` |
| AI mode / scope | derive from REQ FRs (AI-in-scope iff any FR mentions AI/ML/LLM) |
| Risk appetite | `Medium` |
| Anything else | first option in the list |
Document the choice you made in your final report so the orchestrator can record it.
Never block waiting for an answer.
2. Capture the actual file path the skill wrote to. Inside the Write tool call,
the ArcKit `validate-arc-filename.mjs` PreToolUse hook normalizes the path
(allocates the next sequence number for multi-instance types like ADR/DIAG,
moves into the correct subfolder, pads project IDs). The hook returns the
corrected path as `updatedInput.file_path` and the actual write proceeds
there. You will see this corrected path in the Skill tool's result.
Read `ACTUAL_PATH` from that result. Do NOT call `generate-document-id.sh`
yourself or construct paths by string substitution — the hook is the
authoritative path allocator.
3. Sanity check the corrected path via Bash:
- `test -f "$ACTUAL_PATH"` returns success
- `[ "$(wc -l < "$ACTUAL_PATH")" -gt 100 ]`
- `grep -c '^## Document Control\|^| Document ID' "$ACTUAL_PATH"` returns ≥ 1
4. Do NOT git commit. Do NOT modify other files. The orchestrator handles version control.
Report back ≤ 200 words:
- Actual file path written + exact line count
- Top 3 findings, scores, or RAG ratings (whatever the skill produces as headline result)
- Validation result: PASS or FAIL (with reason)
- Any failures, partial completions, or warnings
- AskUserQuestion choices made (if any)
Do NOT include the document content in your report. Just the summary.
When all return, collect summaries.
For each target in wave:
test -f).wc -l).grep -c '^## Document Control' ≥ 1).Read projects/{P}-{NAME}/.arckit/state.json, update each target with:
{
"<TARGET_ID>": {
"status": "complete",
"path": "{ACTUAL_PATH}",
"built_at": "{ISO_TIMESTAMP}",
"wave": {WAVE_N},
"line_count": {LC},
"skill": "{SKILL}",
"topic": "{TOPIC_OR_NULL}",
"agent_summary": "{≤200-word agent report}",
"input_hashes": {
"<DEP_ID>": "{SHA256_OF_state.targets[DEP_ID].path}"
}
}
}
Compute input_hashes via Bash sha256sum on each resolved dep's state.targets[DEP_ID].path immediately before persisting state. Skip deps whose target has no recorded path (e.g. external inputs). Targets with no deps get input_hashes: {}.
For failures: status: "failed", error: "...", wave: {WAVE_N} — do not record input_hashes for failed targets.
If --no-commit not set:
git add {OUTPUT_PATHS} projects/{P}-{NAME}/.arckit/state.json
git commit -m "$(cat <<'EOF'
Build wave {N}: {targets joined} via arckit-build
{One-line per target with line count and headline result}
Co-Authored-By: Claude Code <[email protected]>
EOF
)"
If any agent in the wave reported FAIL or validation failed:
status: "failed", error: "...", wave: {WAVE_N} for failed targets, and status: "complete" for the targets in the wave that did succeed. State is needed for --resume.--resume once fixed.Otherwise, proceed.
projects/{P}-{NAME}/.arckit/state.json:
{
"state_format_version": "0.4",
"project_id": "001",
"project_name": "001-arckit-saas",
"recipe": "uk-saas",
"recipe_path": ".claude/skills/arckit-build/recipes/uk-saas.yaml",
"started_at": "2026-05-03T16:00:00Z",
"last_wave_completed": 5,
"current_wave": 6,
"targets": {
"PRIN": {"status": "complete", "path": "projects/000-global/ARC-000-PRIN-v1.0.md", "wave": 0, "source": "pre-existing", "input_hashes": {}},
"REQ": {"status": "complete", "path": "...", "wave": 1, "source": "pre-existing", "input_hashes": {"PRIN": "44e7...bc92"}},
"RISK": {"status": "complete", "path": "...", "wave": 3, "skill": "arckit:risk", "input_hashes": {"REQ": "9f2a...c41e", "STKE": "1b88...07ad", "PRIN": "44e7...bc92"}},
"SVCASS": {"status": "pending"}
},
"waves": [
{"n": 0, "targets": ["PRIN"], "status": "complete", "completed_at": "..."},
{"n": 3, "targets": ["RISK", "STRATEGY"], "status": "complete", "completed_at": "..."}
]
}
State written by older versions (state_format_version: "0.3") is read-compatible: targets without input_hashes are treated as if all hashes match (no spurious rebuild on upgrade). The next successful build of any such target records its hashes and migrates the entry to 0.4 in place. The orchestrator rewrites state_format_version to "0.4" on first write.
Parse arguments from skill input (project, --plan, --resume, --recipe, --enable, --exclude, etc.). If project not specified, ask user.
Detect project: resolve <project> arg → projects/{P}-{slug}/. Confirm directory exists.
Load recipe: resolve --recipe NAME (default uk-saas) against the precedence list. Read the YAML with the Read tool. Validate top-level shape (recipe, schema_version, targets, defaults.version). Halt with a clear error if the recipe file is missing or malformed.
Resolve enabled targets: drop optional_targets whose default: false unless --enable ID was passed; drop optional_targets named in --exclude ID. Apply {P}/{NAME}/{V}/{TOPIC} substitution to every args and output.project field.
Load state.json at projects/{P}-{NAME}/.arckit/state.json. If absent, scan project dir for existing ARC-{P}-*-v*.md files and infer initial state.
Subagent capability smoke-test (first wave only, skip on --resume): before dispatching the real wave, spawn one throwaway general-purpose Agent with this prompt:
"Examine your system-reminder messages — they enumerate the skills available in this conversation. Return exactly one line:
AVAILABLEif the list containsarckit:principles(or any otherarckit:*skill).NOT_AVAILABLEotherwise. Do NOT invoke any skill. Do NOT call any tool other than reading your own context."
This is a metadata check, not a skill invocation — it should complete in seconds. If the response is NOT_AVAILABLE, halt: subagents in this session do not have access to plugin skills (Failure mode #1). Suggest enabling the plugin at user-scope or running the harness from a session where claude --print '/skill list' shows the arckit:* family.
Compute work list: apply the staleness rules from § "Input-hash change detection". done = targets where status: complete AND file exists AND every recorded input hash still matches AND no transitive dep is stale (steps 2–3 of the staleness rules). pending = enabled-targets − done. Stale targets have their state.targets[id].status rewritten to "stale" and re-enter the wave plan. With --skip-hash-check, skip the hash + cascade checks (test -f only).
If --plan: print plan (each wave + targets + line (skip|build) target ← deps), exit.
For each wave (sequential outer loop):
--no-commit.Post-build hooks: spawn parallel agents — one per recipe.post_build_hooks[] entry.
Final report:
/goal (Claude Code v2.1.139+)/goal keeps Claude working across turns until a completion condition is met, showing live elapsed / turns / tokens overhead. It composes naturally with this build harness when the user's intent stretches beyond a single recipe pass:
/goal every artefact under projects/001-*/ has Document Control Status: APPROVED and no Next Review Date in the past, then run /arckit:build 001 --recipe uk-saas --resume. The harness rebuilds stale targets; /goal keeps re-running it until the post-condition holds./goal no artefact under projects/001-*/ has been flagged by the stale-artifact-scan monitor, then /arckit:build 001 --refresh REQ (or whichever target the monitor flagged)./arckit:conformance violations and a green /arckit:health scan; /goal will sequence build → conformance → health → refresh-violator → build until clean.Caveats:
/goal is Claude Code only (not exposed in Codex / OpenCode / Gemini). Document the manual loop ("re-run /arckit:build --resume until state.json shows all targets complete") for non-Claude runtimes.session-learner, session-end-stamp) are observational and never block, so the cap should not interfere./goal per session; don't nest. The harness's own halt-on-fail still fires inside the goal loop.arckit:* skills — detected by the smoke-test in step 6 of the run order; halts the build before any wave dispatches. Workaround if smoke-test fails: load the skill prompt in main context once, pass as plain text to agent (deferred to v0.4+)."Recipe 'uae-federal-ai' not found. It ships in the arckit-uae community plugin. Install with: claude plugin install arckit-uae". The orchestrator maps recipe name to expected plugin via the built-in recipes table; recipes the table doesn't know about fall back to the generic precedence-list error.args field should be specific enough to skip interaction in the first place.(output.project, output.type, output.subfolder, multi_instance) tuples for non-multi-instance targets, and unique ids for multi-instance ones.test -f. Edits are caught by the SHA-256 hash check (§ "Input-hash change detection") — the edited artefact's downstream targets are marked stale and rebuilt in dep order. Use --skip-hash-check to bypass.ADR-*) are expanded before cycle detection.arckit:* skill prompts in main context once and inline them in worker prompts when the smoke-test returns NOT_AVAILABLE. (File-hash change detection shipped in v0.4 — see § "Input-hash change detection".)extends: uk-saas); hash external inputs (e.g. external/policies/*.md) in addition to dep artefacts.--validate-only for GitHub Actions).arckit:artefact-worker subagent type; recipe "Expected output path" computed from skill metadata (single source of truth).npx claudepluginhub tractorjuice/arckit-claude --plugin arckit-agent-architecture2plugins reuse this skill
First indexed Jul 14, 2026
Orchestrates parallel builds of ArcKit artefacts using subagent isolation, dependency DAG, and resumable state.
Orchestrates code implementation workflows: swift/quick changes, standard implementations, build-simplify-review cycles. Routes by user intent or detects state from project reports.
Establishes Arc's skill routing, instruction priority, and bootstrap rules. Invoke at session start to activate Arc's workflow control plane.