@wairon/cli 5.1.1-dev.94 → 5.1.1-dev.96
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/dist/cli/index.js +3237 -535
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +2782 -424
- package/dist/index.js.map +1 -1
- package/dist/templates/skills/sdd-architect.md +3 -2
- package/dist/templates/skills/sdd-delegate.md +2 -2
- package/dist/templates/skills/sdd-implement.md +1 -1
- package/package.json +1 -1
|
@@ -107,7 +107,8 @@ schemas:
|
|
|
107
107
|
- **targetLanguage**: set on L0 (`sdd_initialize_system`), override per L1 — enables language-aware validation (foreign builtins and flow constructs the language lacks are flagged). Extension packs (`.wai/project.yaml` → `extensions.packs`) may register additional languages/platforms and custom profiles.
|
|
108
108
|
- **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.
|
|
109
109
|
- **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.
|
|
110
|
-
- **Methods (L3)**: prefer structured `params: [{name, type}]` — authoritative for type checking; the prose `signature` is then display-only.
|
|
110
|
+
- **Methods (L3)**: prefer structured `params: [{name, type}]` — authoritative for type checking; the prose `signature` is then display-only.
|
|
111
|
+
- **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; and `async T` (or `async void`) on a returns that completes later. 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). `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.
|
|
111
112
|
- **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).
|
|
112
|
-
- **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` tags and its writes need a read-back reachable from a lifecycle `init` flow (`MISSING_HYDRATION`); `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 `
|
|
113
|
+
- **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` tags and its writes need a read-back reachable from a lifecycle `init` flow (`MISSING_HYDRATION`); `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`).
|
|
113
114
|
- **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.
|
|
@@ -23,13 +23,13 @@ You are the **Delegation Orchestrator**. Your job is to hand scoped work to a fo
|
|
|
23
23
|
- Pick the agent whose `ownedPaths`/domain matches the task. If no agent fits, stop and tell the user the topology has a gap.
|
|
24
24
|
2. **Fetch the LIVE brief**:
|
|
25
25
|
- Call `sdd_get_agent_brief(agentId)` (or read the `wairon-agent://<agentId>` resource).
|
|
26
|
-
- The brief carries: `agentId`, `name`, `template`, `domainRoot?`, `ownedPaths`, `readPaths?`, `instructions`, `variantGuidance?`, and — when the project opted into `execution.tier` — `profile` and `budget`.
|
|
26
|
+
- The brief carries: `agentId`, `name`, `template`, `domainRoot?`, `ownedPaths`, `readPaths?`, `instructions`, `variantGuidance?`, `typeMapping?` (how the contracts' neutral types are spelled in the language the agent's code is written in, also folded into `instructions` under `## Types in <language>`), and — when the project opted into `execution.tier` — `profile` and `budget`.
|
|
27
27
|
- **Never reuse a brief across delegations or after a re-lock** — fetch fresh per delegation; the call is cheap and the brief is always current.
|
|
28
28
|
3. **Spawn a GENERIC subagent from the brief**:
|
|
29
29
|
- Prompt: `brief.instructions`, plus the concrete task description.
|
|
30
30
|
- Write fence: the subagent may only modify files matching `brief.ownedPaths` (within `brief.domainRoot` when set).
|
|
31
31
|
- Required first reading: `brief.readPaths` — the subagent reads these before any edit.
|
|
32
|
-
- Pass `brief.variantGuidance` along when present.
|
|
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
33
|
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
34
|
- `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
35
|
- `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.
|
|
@@ -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.
|
|
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.
|
|
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"
|