@wairon/cli 5.1.1-dev.108 → 5.1.1-dev.109
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/CONTRIBUTING.md +193 -0
- package/README.md +14 -11
- package/dist/cli/index.js +2694 -1819
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +130 -7
- package/dist/index.js +2235 -1397
- package/dist/index.js.map +1 -1
- package/docs/cli.md +74 -23
- package/docs/design/approval-baseline.md +257 -0
- package/docs/design/connecting-agent-entrypoint.md +167 -0
- package/docs/design/execution-budgets.md +199 -0
- package/docs/design/pack-scoping.md +581 -0
- package/docs/design/supervisor-doctrine.md +110 -0
- package/docs/extending-wairon.md +2 -2
- package/package.json +9 -3
- package/schemas/design-export-2.json +9 -1
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Supervisor and Actor doctrine: supervision state, shared data, the lifecycle effect
|
|
2
|
+
|
|
3
|
+
## The problem
|
|
4
|
+
|
|
5
|
+
Two rules left the process layer without an honest shape.
|
|
6
|
+
|
|
7
|
+
- Held state lives in a dedicated data component, but a Supervisor could not
|
|
8
|
+
depend on a Store, Registry, Repository, Index or Query at all
|
|
9
|
+
(`ARCHITECTURE_VIOLATION_SUPERVISOR_DEP`). A Supervisor's own bookkeeping —
|
|
10
|
+
restart counts, the set of live children, the brackets of the runs it starts —
|
|
11
|
+
had nowhere to live.
|
|
12
|
+
- A component depending on a live Actor had to also depend on a Supervisor that
|
|
13
|
+
supervises it (`ACTOR_REACHED_WITHOUT_SUPERVISOR`). Real callers do not go
|
|
14
|
+
through the Supervisor: they look the Actor's live handle up by id in a
|
|
15
|
+
registry the Supervisor keeps. The remedy pushed a ceremonial edge instead of
|
|
16
|
+
the real lookup hop.
|
|
17
|
+
|
|
18
|
+
## The rules
|
|
19
|
+
|
|
20
|
+
1. **Supervision state.** A Supervisor may `owns` a Store or Registry that is its
|
|
21
|
+
own: one hop, private, read and written in full. It owns nothing else, and
|
|
22
|
+
nobody else depends on that state.
|
|
23
|
+
2. **Shared data.** A Supervisor may call a data component it does not own only
|
|
24
|
+
through methods whose declared effect is `read` or `lifecycle`. A write goes
|
|
25
|
+
through a workflow: the Supervisor depends on the Orchestrator that does it.
|
|
26
|
+
Judged from the Supervisor's narrative call steps against the callee's
|
|
27
|
+
declared effect; a callee that declares no effect is refused too.
|
|
28
|
+
3. **The lifecycle effect.** A third method effect, `lifecycle`: the method
|
|
29
|
+
creates, destroys, or (un)registers an entity's existence or membership and
|
|
30
|
+
never modifies its domain fields. It is closed under composition: a lifecycle
|
|
31
|
+
method calls only read and lifecycle methods besides construction and local
|
|
32
|
+
steps.
|
|
33
|
+
4. **Supervised reach.** A component depending on a live Actor reaches it through
|
|
34
|
+
its supervision when it also depends on a Supervisor that supervises the
|
|
35
|
+
Actor, or on a Registry such a Supervisor maintains — by owning it, or by
|
|
36
|
+
calling it with lifecycle-effect methods.
|
|
37
|
+
|
|
38
|
+
**Honest limit.** A `read` made on behalf of a request still passes. In practice
|
|
39
|
+
the paired write is refused, which forces the marshalling workflow out, and the
|
|
40
|
+
read moves with it.
|
|
41
|
+
|
|
42
|
+
## Codes
|
|
43
|
+
|
|
44
|
+
| Code | Severity | Rule | Reported on | Meaning |
|
|
45
|
+
|---|---|---|---|---|
|
|
46
|
+
| `SUPERVISOR_CONTAINMENT` | error | pattern-containment | the Supervisor | it owns something other than a Store or Registry |
|
|
47
|
+
| `SUPERVISION_STATE_INTRUSION` | error | member-visibility | the intruder | "X depends on Y, which Supervisor Z owns as its supervision state" |
|
|
48
|
+
| `SUPERVISOR_WRITE_SHORTCUT` | error | supervisor-shared-data (new) | the Supervisor's implementation | a call to a write-effect or untagged method on data it does not own |
|
|
49
|
+
| `LIFECYCLE_CALLS_WRITE` | error | lifecycle-effect-closure (new) | the implementation | a lifecycle-effect method calls a write-effect method |
|
|
50
|
+
| `ARCHITECTURE_VIOLATION_SUPERVISOR_DEP` | error | entrypoint-dependencies | the Supervisor | kept, narrowed: a Supervisor depending on a presentation block |
|
|
51
|
+
| `ACTOR_REACHED_WITHOUT_SUPERVISOR` | error | entrypoint-dependencies | the caller | kept, widened: Registry reach counts; the remedy names the Registry, or says to model one |
|
|
52
|
+
| `BLOCK_OWNS_MEMBERS` | error | pattern-membership | the block | kept: a Supervisor is exempt |
|
|
53
|
+
| `SHARED_OWNED_MEMBER` | error | pattern-membership | the later claimant | kept: Supervisors claim like patterns |
|
|
54
|
+
| `UNUSED_LINT_ALLOW` | warning | lint-allows | the allowing spec | kept: an allow naming an error now says an error cannot be allowed |
|
|
55
|
+
|
|
56
|
+
The existing readers of `effect` read `lifecycle` as a mutation:
|
|
57
|
+
`PORTAL_WRITE_SHORTCUT` refuses a Portal's direct lifecycle call as it refuses a
|
|
58
|
+
write, and a durable Store needs a hydration read-back for its lifecycle methods
|
|
59
|
+
as for its writes (`MISSING_HYDRATION`). The invariant registry still asks only
|
|
60
|
+
write-effect methods to assert invariants, since a lifecycle method never
|
|
61
|
+
modifies domain fields.
|
|
62
|
+
|
|
63
|
+
Within the brief, three choices were made:
|
|
64
|
+
|
|
65
|
+
- Exclusivity is its own code rather than a reworded `VISIBILITY_VIOLATION`:
|
|
66
|
+
the remedy differs (there is no facade to depend on instead; the state is
|
|
67
|
+
either shared data or reached through the Supervisor).
|
|
68
|
+
- An owned Registry counts as maintained for supervised reach, as decided. A
|
|
69
|
+
caller depending on it is then still an intruder, so that shape reports
|
|
70
|
+
`SUPERVISION_STATE_INTRUSION` once and no actor finding: a lookup Registry
|
|
71
|
+
callers share is shared data the Supervisor keeps through lifecycle calls.
|
|
72
|
+
- The lint-allow audit decides "error" from what the run saw on that spec (a
|
|
73
|
+
finding of the code landed there as an error) or, when nothing fired there,
|
|
74
|
+
from the code's resolved severity (project override, profile, default). The
|
|
75
|
+
validator now hands the rule context each code's default severity.
|
|
76
|
+
|
|
77
|
+
## How the four motivating cases validate
|
|
78
|
+
|
|
79
|
+
1. **An orchestrator calls an Actor whose handle it resolves through a router
|
|
80
|
+
that is really a Registry of live handles, mistyped as a Store.** Typed as a
|
|
81
|
+
Store, the caller reaches the Actor through no supervision and
|
|
82
|
+
`ACTOR_REACHED_WITHOUT_SUPERVISOR` fires on the caller. Retyped as a
|
|
83
|
+
Registry whose register/unregister methods are `lifecycle` and whose lookup
|
|
84
|
+
is `read`, with the Supervisor registering each started Actor through a
|
|
85
|
+
lifecycle call, the caller depending on that Registry and the Actor is
|
|
86
|
+
supervised reach, and the Supervisor's calls pass `SUPERVISOR_WRITE_SHORTCUT`.
|
|
87
|
+
A standalone Registry still needs a Store to write to
|
|
88
|
+
(`REGISTRY_WITHOUT_STORE`, a warning) — give the handles a Store, or wrap both
|
|
89
|
+
in a Repository the Supervisor keeps through lifecycle calls.
|
|
90
|
+
2. **A component that spawns and owns Actors is typed Orchestrator but is a
|
|
91
|
+
fused Supervisor and workflow.** It depends on the Actor with no Supervisor
|
|
92
|
+
anywhere: `ACTOR_REACHED_WITHOUT_SUPERVISOR`, whose remedy says to give the
|
|
93
|
+
Actor a Supervisor that maintains a handle Registry. Split into a Supervisor
|
|
94
|
+
(spawns, restarts, registers handles) and a workflow (looks the Actor up in
|
|
95
|
+
that Registry), the tree validates.
|
|
96
|
+
3. **A scheduler Supervisor reads guard state and brackets run lifetimes on a
|
|
97
|
+
shared repository.** The edge to the repository is no longer a finding. Its
|
|
98
|
+
calls — read the guard, open a run, count live runs, close the run — are
|
|
99
|
+
`read`, `lifecycle`, `read`, `lifecycle`: quiet. Tagging open or close as
|
|
100
|
+
`write`, or leaving them untagged, fires `SUPERVISOR_WRITE_SHORTCUT`; a
|
|
101
|
+
lifecycle open that also updates the run's fields fires
|
|
102
|
+
`LIFECYCLE_CALLS_WRITE` on the repository's implementation.
|
|
103
|
+
4. **The same Supervisor reads and writes a shared object heap on behalf of a
|
|
104
|
+
call.** The read passes; the write fires `SUPERVISOR_WRITE_SHORTCUT`. Moving
|
|
105
|
+
the work into a marshalling Orchestrator the Supervisor calls — the read goes
|
|
106
|
+
with it — validates.
|
|
107
|
+
|
|
108
|
+
All four, and a fire and a control for every new or changed code, are fixtures
|
|
109
|
+
in `tests/rules-matrix/families/boundaries-supervision.fixtures.ts`; the
|
|
110
|
+
lint-allow case is in `references-lint-allows.fixtures.ts`.
|
package/docs/extending-wairon.md
CHANGED
|
@@ -17,7 +17,7 @@ silently rot.
|
|
|
17
17
|
|
|
18
18
|
> **New model (preferred).** Installing a pack makes it *available*; a project
|
|
19
19
|
> then *selects* it. Installing no longer grants a pack authority over every
|
|
20
|
-
> project on the machine — see [pack scoping](
|
|
20
|
+
> project on the machine — see [pack scoping](design/pack-scoping.md).
|
|
21
21
|
|
|
22
22
|
```sh
|
|
23
23
|
wairon pack install ./appenser-1.2.0.wpack # into this wairon install's store
|
|
@@ -98,7 +98,7 @@ arguments** — each selection carries its own source, so one command restores a
|
|
|
98
98
|
project's doctrine anywhere:
|
|
99
99
|
|
|
100
100
|
```yaml
|
|
101
|
-
- uses: SYW-Apps/Waffle-AIron/.github/actions/setup-wairon@
|
|
101
|
+
- uses: SYW-Apps/Waffle-AIron/.github/actions/setup-wairon@v<version> # the version you lock with (see docs/cli.md)
|
|
102
102
|
with:
|
|
103
103
|
packs: sync # sync (default) | none (bundled repos) | explicit sources
|
|
104
104
|
- run: npm ci # a TS/JS project with code: its own dependencies first (see docs/cli.md)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wairon/cli",
|
|
3
|
-
"version": "5.1.1-dev.
|
|
3
|
+
"version": "5.1.1-dev.109",
|
|
4
4
|
"description": "SYW Waffle AIron — CLI for managing AI coding agent topology across projects",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -30,7 +30,13 @@
|
|
|
30
30
|
"schemas",
|
|
31
31
|
"README.md",
|
|
32
32
|
"docs/*.md",
|
|
33
|
-
"docs/standards/**"
|
|
33
|
+
"docs/standards/**",
|
|
34
|
+
"docs/design/supervisor-doctrine.md",
|
|
35
|
+
"docs/design/pack-scoping.md",
|
|
36
|
+
"docs/design/connecting-agent-entrypoint.md",
|
|
37
|
+
"docs/design/execution-budgets.md",
|
|
38
|
+
"docs/design/approval-baseline.md",
|
|
39
|
+
"CONTRIBUTING.md"
|
|
34
40
|
],
|
|
35
41
|
"workspaces": [
|
|
36
42
|
"sdk"
|
|
@@ -72,6 +78,7 @@
|
|
|
72
78
|
"js-yaml": "^4.1.0",
|
|
73
79
|
"ora": "^5.4.1",
|
|
74
80
|
"swagger-ui-dist": "^5.32.9",
|
|
81
|
+
"typescript": "^5.5.2",
|
|
75
82
|
"yaml": "^2.9.1",
|
|
76
83
|
"zod": "^3.23.8"
|
|
77
84
|
},
|
|
@@ -87,7 +94,6 @@
|
|
|
87
94
|
"rimraf": "^5.0.7",
|
|
88
95
|
"tsup": "^8.1.0",
|
|
89
96
|
"tsx": "^4.15.7",
|
|
90
|
-
"typescript": "^5.5.2",
|
|
91
97
|
"vitest": "^4.1.9",
|
|
92
98
|
"zod-to-json-schema": "^3.25.2"
|
|
93
99
|
}
|
|
@@ -1102,7 +1102,15 @@
|
|
|
1102
1102
|
"properties": {
|
|
1103
1103
|
"id": {
|
|
1104
1104
|
"type": "string",
|
|
1105
|
-
"
|
|
1105
|
+
"maxLength": 64,
|
|
1106
|
+
"allOf": [
|
|
1107
|
+
{
|
|
1108
|
+
"pattern": "^[a-z0-9-_]+$"
|
|
1109
|
+
},
|
|
1110
|
+
{
|
|
1111
|
+
"pattern": "^(?!(?:con|prn|aux|nul|com[0-9]|lpt[0-9])$)"
|
|
1112
|
+
}
|
|
1113
|
+
]
|
|
1106
1114
|
},
|
|
1107
1115
|
"description": {
|
|
1108
1116
|
"type": "string",
|