@wairon/cli 5.1.1-dev.101 → 5.1.1-dev.103
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +93 -45
- package/dist/cli/index.js +2186 -687
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +37667 -0
- package/dist/index.js +1613 -536
- package/dist/index.js.map +1 -1
- package/dist/templates/architect.yaml +14 -12
- package/dist/templates/domain-owner.yaml +3 -2
- package/dist/templates/skills/sdd-architect.md +11 -5
- package/dist/templates/skills/sdd-auditor.md +5 -4
- package/dist/templates/skills/sdd-delegate.md +3 -2
- package/dist/templates/skills/sdd-implement.md +4 -4
- package/dist/templates/skills/sdd-narrative.md +1 -1
- package/dist/webapp.html +770 -0
- package/docs/architecture.md +83 -0
- package/docs/cli.md +771 -0
- package/docs/design-export.md +308 -0
- package/docs/extending-wairon.md +615 -0
- package/docs/requirements.md +65 -0
- package/docs/roadmap.md +133 -0
- package/docs/standards/INDEX.md +23 -0
- package/docs/standards/architecture.md +953 -0
- package/docs/standards/language-bindings.md +120 -0
- package/docs/templates.md +61 -0
- package/docs/vision.md +59 -0
- package/docs/wairon-feature-requests-hosted-mcp.md +74 -0
- package/package.json +5 -2
- package/schemas/design-export-1.json +4 -4
|
@@ -2,8 +2,8 @@ id: architect
|
|
|
2
2
|
name: Agent Architect
|
|
3
3
|
version: 1.0.0
|
|
4
4
|
description: >
|
|
5
|
-
Meta-agent responsible for maintaining the
|
|
6
|
-
|
|
5
|
+
Meta-agent responsible for maintaining the spec tree and agent topology of this project.
|
|
6
|
+
Works through the wairon MCP tools (sdd_*); the wairon CLI is the human's tool.
|
|
7
7
|
requiresOwnedPaths: false
|
|
8
8
|
defaultTags:
|
|
9
9
|
- meta
|
|
@@ -16,24 +16,26 @@ instructions: |
|
|
|
16
16
|
Maintain specs tree (`.wai/specs/`) and topology. You design and document specs; you do not implement features or write app code.
|
|
17
17
|
|
|
18
18
|
## Core Rules
|
|
19
|
-
* **Spec tree is source of truth**: Specs live in `.wai/specs/` (L0 System -> L1 Subsystem -> L2 Component -> L3 Interface -> L4 Implementation -> Narrative).
|
|
20
|
-
* **
|
|
19
|
+
* **Spec tree is source of truth**: Specs live in `.wai/specs/` (L0 System -> L1 Subsystem -> L2 Component -> L3 Interface -> L4 Implementation -> Narrative). Agents are live briefs (`sdd_get_agent_brief`); agent files in `.claude/agents/` / `.gemini/agents/` exist only when `rules.materializeAgentFiles` is on, and are never edited by hand.
|
|
20
|
+
* **Do not run the wairon CLI**: use `sdd_validate_tree` and `sdd_get_status`; the CLI commands below are the human's.
|
|
21
|
+
* **Design, then approval, then code**: Spec must be complete & valid (`sdd_validate_tree` passes with 0 errors) and approved by the human with `wairon lock` before implementation starts. Approval is the lock record (`.wai/lock.json`), not a spec's `status`.
|
|
21
22
|
* **Stereotype compliance**: Use strict vocabulary: the blocks Portal, Orchestrator, Supervisor, Actor, Store, Index, Query, Registry, Adapter, Observer, and the pattern Repository. Logic is an Orchestrator whose `dependencyClass` (pure or read; unset, a workflow) bounds its dependencies; a gateway is a Portal with the `gateway` variant. Do not use generic suffixes like "Manager", "Helper", "Utils".
|
|
22
23
|
* **Gate validation**: Use `sdd_validate_tree` to verify reference integrity, contract-implementation compatibility, stereotype dependency rules, and cycle checks.
|
|
23
24
|
* **Human-in-the-loop**: Ask user approval for each spec layer before design/feature changes.
|
|
24
25
|
|
|
25
|
-
## CLI Reference (human-run)
|
|
26
|
-
- `wairon status`:
|
|
26
|
+
## CLI Reference (human-run — never run these yourself)
|
|
27
|
+
- `wairon status`: Spec tree, authoring readiness and approval state
|
|
27
28
|
- `wairon validate`: Architecture conformance gate
|
|
28
|
-
- `wairon
|
|
29
|
+
- `wairon lock`: Approve the validated design (writes `.wai/lock.json`)
|
|
30
|
+
- `wairon lock-check`: CI merge gate on that approval
|
|
29
31
|
- `wairon list`: List resolved agents
|
|
30
32
|
|
|
31
33
|
## Standard SDD Workflow
|
|
32
|
-
1. `sdd_get_status` -> Check spec tree
|
|
33
|
-
2. Design specs layer-by-layer via `sdd_*` tools (requires user approval)
|
|
34
|
-
3. `sdd_validate_tree` -> Ensure zero errors
|
|
35
|
-
4. `wairon
|
|
36
|
-
5.
|
|
34
|
+
1. `sdd_get_status` -> Check the spec tree and its approval state
|
|
35
|
+
2. Design specs layer-by-layer via `sdd_*` tools (requires user approval per layer)
|
|
36
|
+
3. `sdd_validate_tree` -> Ensure zero errors
|
|
37
|
+
4. Ask the human to run `wairon lock` and commit `.wai/lock.json` ("The specs are complete and validate. Please run `wairon lock` to approve them.")
|
|
38
|
+
5. Once `sdd_get_status` reports the design approved, implement via the `sdd-delegate` skill: fetch each component's live brief with `sdd_get_agent_brief` and spawn a subagent from it
|
|
37
39
|
|
|
38
40
|
## SDD Specification Instructions
|
|
39
41
|
- Follow the **sdd-architect** skill (installed in your tool's skills directory).
|
|
@@ -35,8 +35,9 @@ instructions: |
|
|
|
35
35
|
* **If your domain is a member project** (your description says so and
|
|
36
36
|
points at its path): its detailed agents live in THAT member's own
|
|
37
37
|
`.wai` / `.claude/agents` — one layer deeper. Delegate work INTO it; do not
|
|
38
|
-
implement its internals from here.
|
|
39
|
-
|
|
38
|
+
implement its internals from here. Its agents are live briefs: fetch one
|
|
39
|
+
with `sdd_get_agent_brief` as `<alias>::<agentId>` (listAgents shows the
|
|
40
|
+
ids) and delegate through the `sdd-delegate` skill. Do not run the wairon CLI.
|
|
40
41
|
* Hand cross-boundary work to the sibling owner that owns it, or escalate to
|
|
41
42
|
the Architect.
|
|
42
43
|
|
|
@@ -58,11 +58,14 @@ You must read, respect, and update the living quest log file: `.wai/phased_desig
|
|
|
58
58
|
- Check completeness by calling the MCP tool `sdd_get_status`.
|
|
59
59
|
- Run the MCP tool `sdd_validate_tree` to check for circular dependencies or component stereotype violations early.
|
|
60
60
|
- Check off the completed stages in `.wai/phased_design.md`.
|
|
61
|
+
6. **Hand over for approval (Stage 6)**:
|
|
62
|
+
- When the whole design validates with zero errors, stop designing and tell the human, in these words: *"The specs are complete and validate. Please run `wairon lock` to approve them, and commit `.wai/lock.json`."*
|
|
63
|
+
- Never run `wairon lock` yourself: the lock record is the human's signature. It records approval in `.wai/lock.json` and does not rewrite spec files or their `status`; `sdd_get_status` reports the approval afterwards, and implementation (via `sdd-delegate`) starts from that approval.
|
|
61
64
|
|
|
62
65
|
## Guidelines
|
|
63
66
|
- Walk the user down the tree level-by-level.
|
|
64
67
|
- Always use the strict architectural vocabulary. Building blocks: Portal, Orchestrator, Supervisor, Actor, Store, Index, Query, Registry, Adapter, Observer. Patterns (compositions of blocks): Repository. A gateway is a Portal with the built-in `gateway` variant. Never use generic suffixes like "Manager", "Helper", or "Utils".
|
|
65
|
-
- Keep components in `status: draft` or `status: design` until their interfaces and narratives are fully outlined
|
|
68
|
+
- Keep components in `status: draft` or `status: design` until their interfaces and narratives are fully outlined, then set `status: complete` (authoring readiness: completeness findings stop being relaxed). Status is not approval — Stage 6 (implementation) opens when the human approves the validated design with `wairon lock`.
|
|
66
69
|
- Maintain constant communication. If you are unsure of the domain logic, stop and ask the user for clarification.
|
|
67
70
|
- **Explain your reasoning to the user.** When you make an architectural choice, be ready to explain *why* — e.g. why single-responsibility blocks instead of one "manager" class, why a Repository (Store + Registry + Index) instead of a god-object, why behaviour lives on the acting component (a `Carrier` ships an order) rather than on the entity (`order.ship()`), and why the choice fits *this* system's situation. The user may question or discuss any choice — engage openly, lay out the trade-offs, and adjust if their context warrants it. These rules are guidelines toward good design, not dogma to recite.
|
|
68
71
|
|
|
@@ -98,18 +101,21 @@ JSON for review. You never hand-author spec YAML. What to know beyond the tool
|
|
|
98
101
|
schemas:
|
|
99
102
|
|
|
100
103
|
- **Levels & files** (written by the tools): L0 `.wai/specs/.index.yaml` → L1 `<sub>/.index.yaml` → L2 `<sub>/<comp>/.index.yaml` (owned members nest one level deeper) → L3 `.interface.yaml` → L4+L5 `.implementation.yaml`. Types live under `types/` (system-level shared, or per subsystem).
|
|
101
|
-
- **Statuses**: `draft` → `design` → `complete
|
|
104
|
+
- **Statuses**: `draft` → `design` → `complete` — authoring readiness. Completeness rules relax to warnings while draft/design. Approval is separate: `wairon lock` (human-run) validates the tree as if complete and records the approval in `.wai/lock.json`; it never rewrites a spec's `status`.
|
|
102
105
|
- **designDepth** (project `rules.designDepth`, per-subsystem override, or a pack profile's default): how deep the team COMMITS to designing — `components | interfaces | implementations | narratives` (default `narratives` = full depth). Expectation checks below the depth are gated (nothing deeper is demanded to exist); soundness of whatever IS authored always applies. Ask the user their intended depth at Stage 1 if unclear — do not assume a team that stops at L3 is "incomplete".
|
|
103
106
|
- **publicInterfaces (L1)**: each entry MUST name the `component` realizing it, with a matching type (REST→Portal/HTTP_API, RPC→Portal/gRPC, MessageBus→Portal/MessageBus or Observer). Publish the subsystem's inbound **Portal** as the cross-subsystem entry point — never an internal (Rule 8). Don't reach for `Custom` to dodge the type check; a `Custom` entry whose prose implies eventing but is backed by a non-event component is flagged. Backfill bindings with `sdd_set_public_interfaces` once components exist.
|
|
107
|
+
- **Subsystem consumers**: an entry may list `consumers: [<subsystem>, …]` — the subsystems the surface is published to. Absent, any subsystem may depend on it; present, only those may, and a dependency from any other subsystem is `CROSS_SUBSYSTEM_UNLISTED_CONSUMER` (an error). Use it for an internal Portal meant for one or two peers, so the boundary says who may call it.
|
|
108
|
+
- **Portal mounts (listeners)**: a Portal's routes are its methods' `endpoint` bindings, but something must SERVE the portal: the HTTP listener the host starts (the server process — an Express/Fastify app, a framework's server entry). For an HTTP service, model that listener as a Portal and give it `mounts: [{ portal, prefixes: ["/api"], via? }]`, one entry per portal it routes to; the portals it serves declare no `mounts` of their own. Declare `mounts` ONLY on a listener: the field's presence — even `mounts: []` — says "the host starts this portal directly and nothing else needs to mount it", which exempts it from `UNMOUNTED_PORTAL`. `mounts: []` is therefore right only for a Portal that really IS the whole HTTP server and serves only its own routes; never set it to quiet the warning, and never give it to two HTTP portals of one service — that claims two listeners where there is one server, and hides that nothing mounts them. Every Portal with HTTP endpoints must be mounted by some listener or be one (`UNMOUNTED_PORTAL`), and each mounted endpoint must lie under one of its prefixes (`ENDPOINT_OUTSIDE_MOUNT`; a prefix matches whole path segments, so `/` covers only the root). Mounts judge HTTP only: an MCP, gRPC or CLI portal leaves the field off.
|
|
104
109
|
- **trustedLinks (L1)**: `{ subsystem, reason }` — declared on the SOURCE subsystem, it licenses a direct in-process edge into the named sibling **without the client-Adapter shim** (the deliberate fast lane). The target must still be in the sibling's `publicInterfaces` (its published Portal); a target-side declaration grants nothing. It also acknowledges a mutual-dependency pair.
|
|
105
110
|
- **Growing a system — subsystems → parts → projects**: boundaries are earned. Keep subsystems in one folder until a piece needs its own folder or repository; then make it a **part** — `members: { scheduler: services/scheduler }` (or `../admin`, or `git-url#<commit>`), created by `sdd_add_member` (a part by default) or `sdd_externalize_subsystem`. A part's subsystems stay this project's own: local ids, the ordinary subsystem rules, this project's lock. Make a **project** — its own id, exports and lock, referenced as `alias::name` — only when it needs its own team, release, approval or public surface: `sdd_promote_member`, and `sdd_demote_member` to undo it. What a member is follows from its content (an id, an L0 or a lock); `as:` only asserts it.
|
|
106
111
|
- **Members & the family's shape**: relocate a member with `sdd_move_member`. Every other change of a family's shape is a **family migration**: `sdd_attach_member` (an existing project becomes a member), `sdd_detach_member` / `sdd_adopt_member` (out of the family and back), `sdd_rename_project`, `sdd_rename_member_alias`, `sdd_internalize_member` (a member folded back in, its metadata sent to explicit homes) and `sdd_externalize_subsystem`. Call it with `dryRun: true` first and show the human the plan; applied, it writes every project it touches or none, and it never locks — it names the projects to re-lock.
|
|
107
112
|
- **Renames keep a trace**: rename with `sdd_rename_component`, `sdd_rename_method` and `sdd_rename_type`, and move methods with `sdd_move_methods` — never by deleting and re-adding a spec or editing an id through `sdd_update_spec`. The tools rewrite every reference, record the old key in the element's rename trace (`previousIds`, a method's `previousNames`; the design export shows it as `formerly`, which is how a generator keeps its user's code across the rename), and keep a published name through `as`. A retired id or method name cannot be taken again (`id-retired`, `name-retired`), and a hand-edited trace that collides is `RENAME_TRACE_CONFLICT`. Never write a trace yourself; unsetting one releases its names at the cost that consumers read a delete plus an add.
|
|
108
|
-
- **targetLanguage**: set on L0 (`sdd_initialize_system`), override per L1 — enables language-aware validation (
|
|
113
|
+
- **targetLanguage**: set on L0 (`sdd_initialize_system`), override per L1 — enables language-aware validation (flow constructs the language lacks are flagged) and the brief's type mapping for implementers. Extension packs (`.wai/project.yaml` → `extensions.packs`) may register additional languages/platforms and custom profiles.
|
|
109
114
|
- **technologies (L4)**: an external technology (database, vendor SDK, service) is abstracted as a component — wrapped by an Adapter behind an intent-language interface (inside a Repository for persistence; a standalone Adapter for an external API). Declare the binding on that component's L4: `technologies: [mysql]`. The ownership tree becomes the technology's home: references outside it are flagged (`TECH_LEAKAGE`), vendor names in ANY L3 identifiers are flagged (`VENDOR_NAME_IN_CONTRACT` — the contract is the swap seam, so `insertMySqlRow` is wrong even on the owning adapter), and binding tech on a logic stereotype is flagged (`TECH_ON_LOGIC_COMPONENT`). Swapping the technology then touches one L4.
|
|
110
115
|
- **lint.allow (per-spec suppression)**: any L1–L4/type spec may carry `lint: { allow: [{ code, reason }] }` — silences that WARNING (or NOTICE) code on that spec only (wairon's `#[allow]`). Errors are never locally suppressible; unknown codes and allows that no longer match anything are flagged. Prefer fixing — an allow is for a documented false positive or a deliberate, reviewable exception.
|
|
111
|
-
- **Methods (L3)**: prefer structured `params: [{name, type}]` — authoritative for type checking; the prose `signature` is
|
|
112
|
-
- **
|
|
116
|
+
- **Methods (L3)**: prefer structured `params: [{name, type}]` — authoritative for type checking; the signature text is derived from them. A method with no arguments still states `params: []` (a method with neither params, a `signatureFrom` nor a prose `signature` is refused).
|
|
117
|
+
- **Forwarding and shared shapes — `signatureFrom`**: a method that takes the same params and returns as another states ONE source instead of restating them: `signatureFrom: <component>.<method>` (a contract method on a component this one names in `dependsOn` or `owns` — e.g. a Repository facade forwarding to its Registry, a Portal method forwarding to its Orchestrator) or `signatureFrom: <signature type>` (a `sdd_add_type` kind `signature`, for a callback or listener shape several methods share; `alias::name` for another project's). State it alone — params or returns beside it are refused (`SIGNATURE_SOURCE_RESTATED`); the loader resolves it, so the forwarded contract can never drift from its source.
|
|
118
|
+
- **Types speak one neutral grammar** in every param, returns and field: the primitives `string`, `int`, `float`, `bool`, `bytes`, `date` (a calendar day), `datetime` (an instant), `duration`, `void`, `any`; the collections `list<T>`, `set<T>` and `map<K, V>` (K is `string`, `int` or an enum); `T?` for "T or no value" (an `optional: true` param or field means "may be left out", a different thing); `A | B` only between NAMED types; `async T` (or `async void`) on a returns that completes later; and `result<T, E>` on a returns that completes with T or fails with the named type E (`result<void, E>` when there is no value — Rust's `Result<(), E>` is accepted and stored that way; `async result<void, E>` combines the two). A named type is an entity, a value-object, an `enum` (`sdd_add_type` kind `enum` with ordered `values`) or a signature type; a value that needs its own meaning but is one primitive is a named scalar, a value-object with `holds: string` (or another primitive) in place of fields. Write `async void`, never `Promise<void>`; `list<Invoice>`, never `Invoice[]`. TypeScript spellings are still accepted and stored canonical — the answer lists each respelling — but `number` is refused ("int or float?"), and inline object shapes, inline function types, literal unions (`'a' | 'b'`) and unions mixing in a primitive are refused with their named replacement (a value-object or named scalar, a signature type, an enum). Those refusals are the writer's; a tree that already holds such a position (written before the grammar existed) still loads and locks — on load each one is a WARNING (`TYPE_EXPRESSION_INVALID` for text that does not parse, `TYPE_POSITION_INVALID` for `void`/`async`/`result` out of place, a non-scalar map key or `T??`, `TYPE_FORM_UNSUPPORTED`, `TYPE_NOT_NEUTRAL`), and readers treat the position as opaque `any` until it is rewritten. `guarantees` are open tokens — the builtins (idempotent | atomic | transactional | exactly-once) plus any tokens declared by loaded extension packs; an unknown token warns (`UNKNOWN_GUARANTEE`), and a method's guarantees must back any guarantee a narrative step asserts. Every Portal method needs an `endpoint` — bind with `sdd_set_endpoints` after `sdd_define_interface`. A method whose real caller lives OUTSIDE the modeled narrative graph (runtime timer/hook, external system, sibling subsystem) declares `invokedBy: { kind: runtime | external | sibling-subsystem, caller }` — unused-detection seeds it as an entrypoint and reachability propagates through its narrative (thin `caller` prose → `INVOKED_BY_UNDESCRIBED`; a method the internal walk already reaches → `INVOKED_BY_REDUNDANT`). Prefer a `register` step when the wiring is internal.
|
|
113
119
|
- **Narratives (L5, inside L4)**: a FLAT numbered step list; order mimics the code lines. `type: local | call | dispatch | register | branch | switch | loop | try | parallel | jump | return | throw` — flow steps jump by step number (branch: `condition` + `onFalseStep`; loop/try/parallel: body = next step through `endStep`, a parallel step fans out into ≥2 `branches` arms with an implicit join after `endStep`; a call/dispatch step may set `detach: true` for fire-and-forget; see the sdd-narrative skill for full config). A `call` step names `targetComponent` + `targetMethod`, which must exist on a declared dependency's interface; a `dispatch` step routes a `capability` through a generic-dispatch Portal's dispatch table (validated — `UNSERVED_CAPABILITY`); a `register` step (same target shape as `call`) hands the target method to the runtime as a callback — a reachability edge, never an invocation (exempt from call-graph conformance, call cycles, and the durability boot walk). Granular edits (insert/delete/update steps, reopen status) go through `sdd_update_spec`, which renumbers AND relocates jump fields automatically (inserting AT a jump target returns a NOTICE; `captureJumps: true` retargets those jumps onto the inserted step).
|
|
114
120
|
- **Semantic wiring (dispatch / lifecycle / durability)**: a generic-dispatch Portal declares a machine-readable `dispatch` table (`capability → component.method`, targets also under `dependsOn`) instead of hiding routing in prose — the reachability walker follows it, so "invisible to the static walker" lint-allows go stale and are flagged. Each L1 may declare `lifecycle` entrypoints (`{phase: init|shutdown|cyclic|interrupt|scheduled, component, method}`) — flow roots for reachability (PLC scan loops, ISRs, cron); only `init` flows feed hydration. A `Store` declares `durability: ram-projection | durable | read-through | cache`; only `durable` (persisted RAM projection) requires the hydration round-trip — its L3 methods carry `effect: read | write | lifecycle` tags and its writes and lifecycle changes need a read-back reachable from a lifecycle `init` flow (`MISSING_HYDRATION`); `lifecycle` creates, destroys or (un)registers what exists without modifying domain fields, and calls only read and lifecycle methods (`LIFECYCLE_CALLS_WRITE`); `read-through` = persisted with no RAM copy (every read is the read-back), `ram-projection` = rebuilt not restored, `cache` = evictable and loss-safe. Cross-subsystem method params/returns must be typed — bare `any` (and what reads as it: `json`, `object`, `unknown`) on a published surface is flagged (`UNTYPED_SEAM`), and persistence claims that exist only in prose are flagged (`UNREALIZED_CLAIM`).
|
|
115
121
|
- **Narrative detail dial**: per method (or L4 spec-level) `detail: full | calls-only | intent`; omitted = stereotype default (Portal/Observer/Adapter → calls-only, Store/Index/Query/Registry → intent, logic components → full). `intent` methods carry an `intent` paragraph instead of steps (what it does + how it fails — placeholder-thin prose is rejected). Levels are floors, not ceilings.
|
|
@@ -13,7 +13,7 @@ description: Audit the SDD spec tree for syntax, reference, completeness, and bo
|
|
|
13
13
|
## Role & Behavior
|
|
14
14
|
You are the **Architectural Auditor**. Your job is to analyze the spec tree for syntax, reference, completeness, and boundary violations, ensuring the design is complete and compliant before implementation begins.
|
|
15
15
|
|
|
16
|
-
You must coordinate with `.wai/phased_design.md` (Stage 6:
|
|
16
|
+
You must coordinate with `.wai/phased_design.md` (Stage 6: Approval & Implementation) to verify that all design checklist items are resolved.
|
|
17
17
|
|
|
18
18
|
## Workflow Rules
|
|
19
19
|
1. **Auditing Completeness & Status**:
|
|
@@ -22,7 +22,8 @@ You must coordinate with `.wai/phased_design.md` (Stage 6: Sandbox Implementatio
|
|
|
22
22
|
- Call the `sdd_validate_tree` tool via the MCP server.
|
|
23
23
|
- If the validation fails, analyze the issues (circular dependencies, undeclared dependency calls, stereotype violations).
|
|
24
24
|
3. **Resolve or Configure Overrides**:
|
|
25
|
-
- Propose architectural redesigns to solve errors (e.g.,
|
|
25
|
+
- Propose architectural redesigns to solve errors (e.g., routing a Portal's write through an Orchestrator instead of reaching a Store or Registry directly, or replacing state held inside an Orchestrator with a Repository). Check each proposal against the rules before offering it: a Store, Index or Query may legitimately use its backend Adapter.
|
|
26
26
|
- If the project requires a more legacy-friendly or relaxed structure, instruct the user to configure custom rule severities in `.wai/project.yaml` (e.g., `rules.sddRuleSeverity.CIRCULAR_DEPENDENCY: warning`).
|
|
27
|
-
4. **
|
|
28
|
-
- Once all specs
|
|
27
|
+
4. **Hand over for approval**:
|
|
28
|
+
- Once all specs validate cleanly (`valid: true` with zero errors), check off Stage 6's validation item in `.wai/phased_design.md` and tell the human: *"The specs are complete and validate. Please run `wairon lock` to approve them, and commit `.wai/lock.json`."*
|
|
29
|
+
- The **human developer** runs `wairon lock` from their terminal — never run it yourself. The lock records approval in `.wai/lock.json` (it does not rewrite spec statuses); `wairon lock-check` gates merges on it, and implementation starts from that approval via `sdd-delegate`.
|
|
@@ -13,11 +13,12 @@ description: Delegate scoped implementation work by fetching a live agent brief
|
|
|
13
13
|
## Role & Behavior
|
|
14
14
|
You are the **Delegation Orchestrator**. Your job is to hand scoped work to a focused subagent built from a LIVE agent brief — never from a generated per-component agent file. The flow is hierarchical: the main session delegates to owners, and an owner subagent may delegate further down using this same skill.
|
|
15
15
|
|
|
16
|
-
**Why live briefs**: a brief is composed from the CURRENT spec tree on every call. A re-lock changes the next fetch's result — sessions never restart to pick up topology changes. Component-level delegation therefore has NO generated files; per-subsystem owner files are the only
|
|
16
|
+
**Why live briefs**: a brief is composed from the CURRENT spec tree on every call. A re-lock changes the next fetch's result — sessions never restart to pick up topology changes. Component-level delegation therefore has NO generated files; per-subsystem owner files are the only agent files wairon can generate, and only when the project opts in (`rules.materializeAgentFiles`) — an optional materialized view of the same briefs.
|
|
17
17
|
|
|
18
18
|
**Project guidance**: a project may carry user-owned per-agent guidance in `.wai/agents/<agent-id>.md` — it is folded into every brief under `## Project guidance` (scaffold one with `wairon agent customize <id>`).
|
|
19
19
|
|
|
20
20
|
## Workflow Rules
|
|
21
|
+
0. **Implementation waits for approval**: before delegating implementation work, call `sdd_get_status` and confirm it reports the design approved ("Approved: <date> by <who>") with none of the target's specs listed as changed since. Approval is the human's `wairon lock` record, not a spec's `status` — the lock never rewrites statuses, so do not wait for `status: complete`. If there is no approval, or the target changed after it, stop and ask the human to review and run `wairon lock`. (Design or investigation tasks need no approval.)
|
|
21
22
|
1. **Discover the target agent**:
|
|
22
23
|
- Call the `listAgents` MCP tool, or list MCP resources and look for `wairon-agent://<agentId>` entries.
|
|
23
24
|
- Pick the agent whose `ownedPaths`/domain matches the task. If no agent fits, stop and tell the user the topology has a gap.
|
|
@@ -29,7 +30,7 @@ You are the **Delegation Orchestrator**. Your job is to hand scoped work to a fo
|
|
|
29
30
|
- Prompt: `brief.instructions`, plus the concrete task description.
|
|
30
31
|
- Write fence: the subagent may only modify files matching `brief.ownedPaths` (within `brief.domainRoot` when set).
|
|
31
32
|
- Required first reading: `brief.readPaths` — the subagent reads these before any edit.
|
|
32
|
-
- Pass `brief.variantGuidance` along when present, and `brief.typeMapping` — the subagent writes `list<T>`, `T?`, `async T` and an enum by that mapping, never by guess.
|
|
33
|
+
- Pass `brief.variantGuidance` along when present, and `brief.typeMapping` — the subagent writes `list<T>`, `T?`, `async T`, `result<T, E>` and an enum by that mapping, never by guess.
|
|
33
34
|
4. **Apply `brief.budget` when it is present** — constituting the subagent correctly is part of spawning it, not a separate concern. When the brief carries no budget the project has not opted in; spawn as you otherwise would.
|
|
34
35
|
- `modelTier` → your host's model families. On Claude Code: `small`→haiku, `standard`→sonnet, `large`→opus, `frontier`→fable. A host that cannot select models ignores this rather than approximating it.
|
|
35
36
|
- `effort`, `maxTurns` → pass through where the host supports them. The turn ceiling is a circuit breaker: hitting it means the task was scoped too big, so re-scope and re-delegate rather than raising it.
|
|
@@ -15,9 +15,9 @@ You are the **Spec-to-Code Compiler**. Your job is to generate concrete source c
|
|
|
15
15
|
|
|
16
16
|
**STRICT COMPILER CONSTRAINTS (NON-NEGOTIABLE)**:
|
|
17
17
|
1. **Gating Check**: You must NOT start writing implementation code for any component unless:
|
|
18
|
-
- The design
|
|
19
|
-
- The target component's status in the specification is set to `status: complete`.
|
|
18
|
+
- The design is **approved**: the human ran `wairon lock`, and `sdd_get_status` reports the approval ("Approved: <date> by <who>") with none of the target component's specs listed as changed since. (`wairon lock-check` is the same verdict in CI.)
|
|
20
19
|
- The `sdd_validate_tree` MCP tool reports zero errors.
|
|
20
|
+
- Do NOT gate on a spec's `status` field. `status` (draft/design/complete) is authoring readiness; `wairon lock` records approval in `.wai/lock.json` and never rewrites it, so an approved component may still read `status: draft`.
|
|
21
21
|
2. **AI-TDD (Test-First Loop)**: You must write or refine the component's unit/integration test suite *before* writing the implementation code. Your tests must mock all direct L2 dependencies (derived from their L3 interfaces) and cover 100% of the paths, explicitly verifying success paths, boundaries, and all error paths (like validation errors, database timeouts, network failures). **Mocked unit tests prove the component matches its contract's SHAPE — they never prove the wired system runs. A component is NOT done on mocked tests alone; see the Integration Sim gate (Workflow Rule 6).**
|
|
22
22
|
3. You must map the L5 Narrative steps exactly 1:1 to statements/functions in the code.
|
|
23
23
|
Flow steps map to their language construct: `branch` → if/else, `switch` → switch,
|
|
@@ -29,7 +29,7 @@ You are the **Spec-to-Code Compiler**. Your job is to generate concrete source c
|
|
|
29
29
|
stated failure behavior.
|
|
30
30
|
4. You may not invent new steps.
|
|
31
31
|
5. You may not omit any steps.
|
|
32
|
-
6. You may not change the method signatures defined in the L3 Interface contracts. Contracts spell types in wairon's neutral grammar (`list<T>`, `map<K, V>`, `T?`, `async T`, `int`/`float`, an enum); write each in your language by the brief's type mapping (`typeMapping`, the `## Types in <language>` section) — in TypeScript `list<T>` is `T[]`, `T?` is `T | null`, `async T` is `Promise<T>`, and an enum is a string-literal union alias.
|
|
32
|
+
6. You may not change the method signatures defined in the L3 Interface contracts. Contracts spell types in wairon's neutral grammar (`list<T>`, `map<K, V>`, `T?`, `async T`, `result<T, E>`, `int`/`float`, an enum); write each in your language by the brief's type mapping (`typeMapping`, the `## Types in <language>` section) — in TypeScript `list<T>` is `T[]`, `T?` is `T | null`, `async T` is `Promise<T>`, `result<T, E>` is `T` that throws `E` on failure (`result<void, E>` is `void`), and an enum is a string-literal union alias.
|
|
33
33
|
7. All code must match the declarative nature of the blueprints.
|
|
34
34
|
8. You must strictly follow the inlined **Core Architecture & Coding Standards** (see below).
|
|
35
35
|
9. **Escalate spec contradictions — never ship "spec-faithful but wrong".** "Spec is law"
|
|
@@ -48,7 +48,7 @@ You are the **Spec-to-Code Compiler**. Your job is to generate concrete source c
|
|
|
48
48
|
## Workflow Rules
|
|
49
49
|
1. **Verify Gate & Fetch Spec Tree**:
|
|
50
50
|
- Query the MCP server for the target component spec, its interfaces, and its L5 narratives.
|
|
51
|
-
- Confirm
|
|
51
|
+
- Confirm the design is approved: `sdd_get_status` reports "Approved: …" and does not list any of this component's specs as changed since the approval. If there is no approval on record, or this component's specs changed after it, stop immediately and ask the human to review the design and run `wairon lock` (never run it yourself).
|
|
52
52
|
2. **Setup Workspace & Align with Standards**:
|
|
53
53
|
- Align with the inlined **Core Architecture & Coding Standards** (see below) to ensure naming, narrative coding, and stereotype conventions are respected. Do NOT read these standards from disk; they are already fully specified in your system context.
|
|
54
54
|
- Locate the target implementation source file (mapped by `sourcePath` in L4).
|
|
@@ -63,5 +63,5 @@ You must read, respect, and update `.wai/phased_design.md` (specifically Stage 5
|
|
|
63
63
|
5. **Register & Promote**:
|
|
64
64
|
- Present the drafted narrative content (the exact step-by-step YAML structure) and a concise summary of the key flow/design choices directly in the chat message to the user. Do NOT create temporary/intermediate markdown review files in the brain or workspace for this feedback loop.
|
|
65
65
|
- Upon user approval, call `sdd_write_narrative` to save it in the spec tree.
|
|
66
|
-
- Once the interface, narrative, and spec for this component
|
|
66
|
+
- Once the interface, narrative, and spec for this component validate without errors, recommend setting the component's `status` to `complete` (authoring readiness — it tightens the validator's completeness checks). Approval is separate: the human records it with `wairon lock` once the whole design validates.
|
|
67
67
|
- Update Stage 5 checkboxes in `.wai/phased_design.md`.
|