compound-workflow 0.1.7 → 0.1.9
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 +4 -2
- package/package.json +1 -1
- package/src/.agents/commands/workflow/brainstorm.md +12 -0
- package/src/.agents/commands/workflow/plan.md +16 -0
- package/src/.agents/commands/workflow/work.md +13 -0
- package/src/.agents/scripts/sync-opencode.mjs +7 -0
- package/src/.agents/skills/xstate-actor-orchestration/SKILL.md +197 -0
- package/src/.agents/skills/xstate-actor-orchestration/agents/openai.yaml +4 -0
- package/src/.agents/skills/xstate-actor-orchestration/assets/statecharts/.gitkeep +0 -0
- package/src/.agents/skills/xstate-actor-orchestration/references/actor-system-patterns.md +71 -0
- package/src/.agents/skills/xstate-actor-orchestration/references/event-contracts.md +73 -0
- package/src/.agents/skills/xstate-actor-orchestration/references/functional-domain-patterns.md +53 -0
- package/src/.agents/skills/xstate-actor-orchestration/references/machine-structure-and-tags.md +36 -0
- package/src/.agents/skills/xstate-actor-orchestration/references/react-container-pattern.md +45 -0
- package/src/.agents/skills/xstate-actor-orchestration/references/reliability-observability.md +39 -0
- package/src/.agents/skills/xstate-actor-orchestration/references/skill-validation.md +33 -0
- package/src/.agents/skills/xstate-actor-orchestration/references/source-map.md +44 -0
- package/src/.agents/skills/xstate-actor-orchestration/references/statechart-review-and-signoff.md +59 -0
- package/src/.agents/skills/xstate-actor-orchestration/references/testing-strategy.md +35 -0
- package/src/.agents/skills/xstate-actor-orchestration/scripts/create-statechart-artifact.sh +71 -0
- package/src/.agents/skills/xstate-actor-orchestration/scripts/validate-skill.sh +138 -0
- package/src/AGENTS.md +4 -2
package/README.md
CHANGED
|
@@ -131,7 +131,9 @@ Full detail: [src/AGENTS.md](src/AGENTS.md), [src/.agents/commands/](src/.agents
|
|
|
131
131
|
|
|
132
132
|
Commands are the public API. Skills and agents are invoked by commands; you don’t call them directly.
|
|
133
133
|
|
|
134
|
-
- **Workflow skills:** `brainstorming`, `file-todos`, `compound-docs`, `document-review`, `technical-review`, `git-worktree`, `agent-browser`, `process-metrics`.
|
|
134
|
+
- **Workflow skills:** `brainstorming`, `file-todos`, `compound-docs`, `document-review`, `technical-review`, `git-worktree`, `agent-browser`, `process-metrics`, `xstate-actor-orchestration`.
|
|
135
|
+
- **XState orchestration trigger:** Use `xstate-actor-orchestration` when complexity exceeds simple local state—UI container-as-orchestrator flows, backend/internal actor orchestration, receptionist/child-actor patterns, retries/timeouts/cancellation, or boolean-flag sprawl.
|
|
136
|
+
- **Skill-local metadata:** Some skills may include tool-specific metadata under `src/.agents/skills/<skill>/agents/` (for example `openai.yaml`) when required by skill validation/runtime.
|
|
135
137
|
- **Guardrail standards:** `data-foundations`, `pii-protection-prisma`, `financial-workflow-integrity`, `audit-traceability` — applied when work touches multi-tenant data, PII, money, or audit.
|
|
136
138
|
- **Agents:** Used by plan, review, and work for research, lint, and validation (e.g. `repo-research-analyst`, `learnings-researcher`, `git-history-analyzer`, `agent-native-reviewer`).
|
|
137
139
|
|
|
@@ -153,7 +155,7 @@ Full “when to use what” and reference standards: [src/AGENTS.md](src/AGENTS.
|
|
|
153
155
|
|
|
154
156
|
**Skills not showing in Cursor?** Cursor discovers skills from (1) the plugin’s `skills/` directory when you load the plugin from this repo, or (2) the project’s `.cursor/skills/` when you use npm: ensure the project has a `.cursor` directory and run `npx compound-workflow install`—Install creates the full structure (`.cursor/skills/<skill>`, `.cursor/agents`, `.cursor/commands`, `.cursor/references`). If skills still don’t appear, check Cursor Settings → Rules and any `permission.skill` settings.
|
|
155
157
|
|
|
156
|
-
**Skills not showing in OpenCode?** OpenCode uses the `.agents/compound-workflow-skills` symlink and `opencode.json` `skills.paths`. Run Install from the project root (`npx compound-workflow install`).
|
|
158
|
+
**Skills not showing in OpenCode?** OpenCode uses the `.agents/compound-workflow-skills` symlink and `opencode.json` `skills.paths`. Run Install from the project root (`npx compound-workflow install`). The learnings-capture skill is named **compound-docs** (hyphen, plural); **compound_doc** (underscore) is an alias that resolves to the same skill.
|
|
157
159
|
|
|
158
160
|
---
|
|
159
161
|
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"compound-workflow","version":"0.1.
|
|
1
|
+
{"name":"compound-workflow","version":"0.1.9","description":"Clarify → plan → execute → verify → capture. One Install action for Cursor, Claude, and OpenCode.","license":"MIT","repository":{"type":"git","url":"git+https://github.com/cjerochim/compound-workflow.git"},"bin":{"compound-workflow":"scripts/install-cli.mjs"},"files":["src","scripts",".cursor-plugin",".claude-plugin","skills"],"engines":{"node":">=18"}}
|
|
@@ -61,6 +61,18 @@ Use **AskQuestion** to suggest:
|
|
|
61
61
|
> planning. Should I run `/workflow:plan` instead, or would you like to
|
|
62
62
|
> explore the idea further?"
|
|
63
63
|
|
|
64
|
+
**State orchestration candidate signals (detection only):**
|
|
65
|
+
|
|
66
|
+
- Multi-step async flow with branching or compensation
|
|
67
|
+
- More than one boolean/flag controlling the same flow
|
|
68
|
+
- Retries, timeouts, cancellation, or recovery requirements
|
|
69
|
+
- Cross-component or cross-service coordination
|
|
70
|
+
- Planned spawned-child actors or receptionist-style actor lookup
|
|
71
|
+
|
|
72
|
+
If these signals appear, note that `/workflow:plan` should evaluate
|
|
73
|
+
`xstate-actor-orchestration`. Do not force architecture decisions in
|
|
74
|
+
brainstorm.
|
|
75
|
+
|
|
64
76
|
---
|
|
65
77
|
|
|
66
78
|
### Phase 1: Understand the Idea
|
|
@@ -83,10 +83,26 @@ Refine the idea through collaborative dialogue using **AskQuestion**:
|
|
|
83
83
|
- **User's intent**: Speed vs thoroughness? Exploration vs execution?
|
|
84
84
|
- **Topic risk**: Security, payments, external APIs warrant more caution
|
|
85
85
|
- **Uncertainty level**: Is the approach clear or open-ended?
|
|
86
|
+
- **State complexity**: Multi-step async branching, retries/timeouts/cancellation, receptionist/child actors, cross-component/service coordination, or boolean-flag sprawl.
|
|
86
87
|
|
|
87
88
|
**Skip option:** If the feature description is already detailed, offer:
|
|
88
89
|
"Your description is clear. Should I proceed with research, or would you like to refine it further?"
|
|
89
90
|
|
|
91
|
+
### 0.5. State-Orchestration Fit Check (Decision in planning)
|
|
92
|
+
|
|
93
|
+
Before finalizing architecture, decide whether to load
|
|
94
|
+
`xstate-actor-orchestration`.
|
|
95
|
+
|
|
96
|
+
Load it when complexity exceeds simple local state, especially for:
|
|
97
|
+
|
|
98
|
+
- UI flows where a React container should orchestrate context/state and
|
|
99
|
+
compose presentational components
|
|
100
|
+
- Backend/internal workflows with hidden state complexity, lifecycle
|
|
101
|
+
management, retries/timeouts/cancellation, or actor coordination
|
|
102
|
+
- Cases where more than one boolean/flag currently controls flow
|
|
103
|
+
|
|
104
|
+
If not selected, document why simpler state management is sufficient.
|
|
105
|
+
|
|
90
106
|
## Main Tasks
|
|
91
107
|
|
|
92
108
|
### 1. Local Research (Always Runs - Parallel)
|
|
@@ -41,6 +41,19 @@ The input must be a plan file path.
|
|
|
41
41
|
- Get user approval to proceed
|
|
42
42
|
- **Do not skip this** - better to ask questions now than build the wrong thing
|
|
43
43
|
|
|
44
|
+
1.1. **Apply state-orchestration trigger (enforcement)**
|
|
45
|
+
|
|
46
|
+
If the plan or implementation involves XState/state-machine
|
|
47
|
+
orchestration, load `xstate-actor-orchestration` before coding.
|
|
48
|
+
|
|
49
|
+
Trigger examples:
|
|
50
|
+
|
|
51
|
+
- React container-as-orchestrator composition for complex UI flows
|
|
52
|
+
- Backend/internal workflow orchestration with hidden complexity
|
|
53
|
+
- Spawned children or receptionist-style actor lookup
|
|
54
|
+
- Retries/timeouts/cancellation/recovery state handling
|
|
55
|
+
- More than one boolean/flag controlling one workflow
|
|
56
|
+
|
|
44
57
|
1.25. **Resolve Repo Defaults (ALWAYS FIRST)**
|
|
45
58
|
|
|
46
59
|
Read `AGENTS.md` and look for the "Repo Config Block" YAML.
|
|
@@ -250,9 +250,16 @@ function main() {
|
|
|
250
250
|
const existing = readJsonMaybeJsonc(opencodeAbs) ?? {};
|
|
251
251
|
const next = structuredClone(existing);
|
|
252
252
|
|
|
253
|
+
const SKILLS_COMPOUND_PATH = ".agents/compound-workflow-skills";
|
|
253
254
|
next.$schema = next.$schema || "https://opencode.ai/config.json";
|
|
254
255
|
next.skills = ensureObject(next.skills);
|
|
255
256
|
next.skills.paths = Array.isArray(next.skills.paths) ? next.skills.paths : [".agents/skills"];
|
|
257
|
+
const hasCompoundWorkflow =
|
|
258
|
+
fs.existsSync(path.join(rootAbs, "node_modules", "compound-workflow")) ||
|
|
259
|
+
fs.existsSync(path.join(rootAbs, SKILLS_COMPOUND_PATH));
|
|
260
|
+
if (hasCompoundWorkflow && !next.skills.paths.includes(SKILLS_COMPOUND_PATH)) {
|
|
261
|
+
next.skills.paths.unshift(SKILLS_COMPOUND_PATH);
|
|
262
|
+
}
|
|
256
263
|
next.command = ensureObject(next.command);
|
|
257
264
|
next.agent = ensureObject(next.agent);
|
|
258
265
|
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: xstate-actor-orchestration
|
|
3
|
+
description: Implement complex interaction models with XState v5 actor systems, including receptionist-style actor lookup with system IDs, orchestrator/coordinator parent actors, cross-actor messaging, lifecycle management with invoke/spawn, persistence and recovery, runtime inspection, and model-based testing. Use when designing or refactoring state-heavy workflows, async process coordination, retries/timeouts, or multi-actor frontend/backend logic in JavaScript or TypeScript.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# XState Actor Orchestration
|
|
7
|
+
|
|
8
|
+
Execute this workflow to design and implement robust interaction models with XState v5.
|
|
9
|
+
|
|
10
|
+
## Workflow
|
|
11
|
+
|
|
12
|
+
1. Model the interaction boundary.
|
|
13
|
+
- Identify external actors (UI, API, queues, timers, humans).
|
|
14
|
+
- Identify internal actors (orchestrator, workers, adapters).
|
|
15
|
+
- Define success, partial success, terminal failure, and compensation behavior.
|
|
16
|
+
|
|
17
|
+
2. Choose actor topology.
|
|
18
|
+
- Use a root orchestrator actor for cross-step coordination and policy decisions.
|
|
19
|
+
- Use worker actors for isolated tasks (IO, retries, transforms).
|
|
20
|
+
- Use receptionist-style lookup (`systemId` + `system.get`) when actors must be discoverable across branches.
|
|
21
|
+
- Use direct parent-child refs when communication can stay local.
|
|
22
|
+
|
|
23
|
+
3. Define event contracts before transitions.
|
|
24
|
+
- Create explicit event unions and payload schemas.
|
|
25
|
+
- Use namespaced event types (`checkout.submit`, `payment.authorized`).
|
|
26
|
+
- Plan wildcard routes for orchestration (`payment.*`, `checkout.*`, `*`) with explicit precedence.
|
|
27
|
+
- Keep error events explicit and typed.
|
|
28
|
+
|
|
29
|
+
4. Compose machine structure before writing actions.
|
|
30
|
+
- Start with nested states to scope events and transitions to relevant regions.
|
|
31
|
+
- Use parallel states when regions are independent and can progress concurrently.
|
|
32
|
+
- Use sequential flow only when one stage must complete before the next starts.
|
|
33
|
+
- Apply tags as stable UI selectors for state intent (`loading`, `error`, `submitting`), not ad-hoc booleans.
|
|
34
|
+
|
|
35
|
+
5. Implement with typed machine setup.
|
|
36
|
+
- Use `setup({...}).createMachine(...)`.
|
|
37
|
+
- Prefer named actions/guards/actors over inline logic.
|
|
38
|
+
- Use `invoke` for state-scoped lifetimes and `spawn`/`spawnChild` for dynamic long-lived workers.
|
|
39
|
+
- Use `emit(...)` for imperative out-of-band notifications when a fire-and-forget signal is needed.
|
|
40
|
+
|
|
41
|
+
6. Add reliability policy.
|
|
42
|
+
- Model retries, backoff, and circuit-breaker behavior as explicit states.
|
|
43
|
+
- Persist snapshots for restart/resume flows when required.
|
|
44
|
+
- Model idempotency boundaries for side effects.
|
|
45
|
+
|
|
46
|
+
7. Add observability.
|
|
47
|
+
- Attach `inspect` at root actor creation for runtime traces.
|
|
48
|
+
- Emit domain-level telemetry from actions, not from random call sites.
|
|
49
|
+
|
|
50
|
+
8. Prove behavior.
|
|
51
|
+
- Add unit tests for guards/actions and transition paths.
|
|
52
|
+
- Add model/path-based coverage for critical flows.
|
|
53
|
+
- Verify timeout, cancellation, and recovery paths.
|
|
54
|
+
|
|
55
|
+
9. Produce statechart review artifact and sign-off package.
|
|
56
|
+
- For every proposed or updated machine, generate a Mermaid statechart artifact.
|
|
57
|
+
- Store artifacts under `assets/statecharts/`.
|
|
58
|
+
- Treat the diagram as required for review discussion and final sign-off.
|
|
59
|
+
- Record review notes and approval in a paired sign-off file.
|
|
60
|
+
- Add or update the artifact at the current workflow phase:
|
|
61
|
+
- Brainstorm: create a draft diagram for option discussion.
|
|
62
|
+
- Implementation plan: refine the diagram into the proposed target design.
|
|
63
|
+
- Implementation/delivery: finalize the as-built diagram and complete sign-off.
|
|
64
|
+
|
|
65
|
+
## Pattern Selection
|
|
66
|
+
|
|
67
|
+
Use the references selectively:
|
|
68
|
+
- Start with [references/source-map.md](references/source-map.md) to pick source docs.
|
|
69
|
+
- Use [references/actor-system-patterns.md](references/actor-system-patterns.md) for receptionist/orchestrator structures.
|
|
70
|
+
- Use [references/event-contracts.md](references/event-contracts.md) before coding transitions.
|
|
71
|
+
- Use [references/functional-domain-patterns.md](references/functional-domain-patterns.md) for pure transforms and early-return style.
|
|
72
|
+
- Use [references/machine-structure-and-tags.md](references/machine-structure-and-tags.md) for nested/parallel composition and tags.
|
|
73
|
+
- Use [references/react-container-pattern.md](references/react-container-pattern.md) for React integration with containers and pure components.
|
|
74
|
+
- Use [references/reliability-observability.md](references/reliability-observability.md) for persistence/inspection/retry policy.
|
|
75
|
+
- Use [references/testing-strategy.md](references/testing-strategy.md) for verification.
|
|
76
|
+
- Use [references/statechart-review-and-signoff.md](references/statechart-review-and-signoff.md) for required Mermaid artifact workflow.
|
|
77
|
+
- Use [references/skill-validation.md](references/skill-validation.md) to validate skill quality without Python tooling.
|
|
78
|
+
|
|
79
|
+
## Implementation Rules
|
|
80
|
+
|
|
81
|
+
- Keep orchestrator context small and policy-focused.
|
|
82
|
+
- Keep domain/entity object transformations in pure functions or dedicated modules, not large inline action bodies.
|
|
83
|
+
- Use immutable transforms (`input -> output`) that are directly unit-testable.
|
|
84
|
+
- Use early returns in actions/guards/transforms instead of deep nested `if/else` trees.
|
|
85
|
+
- Never model machine control flow with booleans; represent control flow with states, substates, and tags.
|
|
86
|
+
- Do not send untyped catch-all events (`{ type: 'ERROR', data: any }`).
|
|
87
|
+
- Route by event namespace first, then by event detail.
|
|
88
|
+
- Keep wildcard transitions as fallback, not primary business routing.
|
|
89
|
+
- Prefer one-way responsibilities: orchestrator decides; workers execute; adapters translate external systems.
|
|
90
|
+
- In React, use container components as controllers that bind actor refs/selectors to presentational components.
|
|
91
|
+
- Keep presentational components pure; they receive props and render only.
|
|
92
|
+
- Use `useSelector` to read actor snapshot/state/context in containers.
|
|
93
|
+
- Use `useEffect` to subscribe to emitted actor events for fire-and-forget UI effects (toasts, navigation, analytics).
|
|
94
|
+
- Do not complete machine review without a Mermaid statechart and a sign-off record.
|
|
95
|
+
|
|
96
|
+
## Validation (No Python Required)
|
|
97
|
+
|
|
98
|
+
Run:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
./scripts/validate-skill.sh .
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Validate before proposing completion:
|
|
105
|
+
- Frontmatter includes only `name` and `description`.
|
|
106
|
+
- `name` matches folder naming rules.
|
|
107
|
+
- `agents/openai.yaml` includes a `default_prompt` mentioning `$<skill-name>`.
|
|
108
|
+
- No unresolved TODO placeholders remain.
|
|
109
|
+
- Local references linked from `SKILL.md` exist.
|
|
110
|
+
- `assets/statecharts/` exists for diagram artifacts.
|
|
111
|
+
|
|
112
|
+
Generate a new artifact bundle:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
./scripts/create-statechart-artifact.sh . <machine-name> [timestamp] [DRAFT|PLANNED|APPROVED]
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Minimal Starter Skeleton
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
import { setup, assign, sendTo, fromPromise } from 'xstate';
|
|
122
|
+
|
|
123
|
+
type FlowEvent =
|
|
124
|
+
| { type: 'flow.start'; input: { orderId: string } }
|
|
125
|
+
| { type: 'payment.ok'; txnId: string }
|
|
126
|
+
| { type: 'payment.fail'; reason: string }
|
|
127
|
+
| { type: 'flow.cancel' };
|
|
128
|
+
|
|
129
|
+
interface FlowContext {
|
|
130
|
+
orderId?: string;
|
|
131
|
+
txnId?: string;
|
|
132
|
+
error?: string;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const paymentLogic = fromPromise(async ({ input }: { input: { orderId: string } }) => {
|
|
136
|
+
return { txnId: `txn-${input.orderId}` };
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
export const flowMachine = setup({
|
|
140
|
+
types: {
|
|
141
|
+
context: {} as FlowContext,
|
|
142
|
+
events: {} as FlowEvent,
|
|
143
|
+
},
|
|
144
|
+
actors: {
|
|
145
|
+
paymentLogic,
|
|
146
|
+
},
|
|
147
|
+
actions: {
|
|
148
|
+
captureInput: assign(({ event }) =>
|
|
149
|
+
event.type === 'flow.start' ? { orderId: event.input.orderId } : {}
|
|
150
|
+
),
|
|
151
|
+
setError: assign(({ event }) =>
|
|
152
|
+
event.type === 'payment.fail' ? { error: event.reason } : {}
|
|
153
|
+
),
|
|
154
|
+
notifyWorker: sendTo('payment-worker', ({ context }) => ({
|
|
155
|
+
type: 'run',
|
|
156
|
+
orderId: context.orderId,
|
|
157
|
+
})),
|
|
158
|
+
},
|
|
159
|
+
}).createMachine({
|
|
160
|
+
id: 'flow.orchestrator',
|
|
161
|
+
initial: 'idle',
|
|
162
|
+
context: {},
|
|
163
|
+
states: {
|
|
164
|
+
idle: {
|
|
165
|
+
on: {
|
|
166
|
+
'flow.start': {
|
|
167
|
+
target: 'authorizing',
|
|
168
|
+
actions: 'captureInput',
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
authorizing: {
|
|
173
|
+
invoke: {
|
|
174
|
+
id: 'payment-worker',
|
|
175
|
+
src: 'paymentLogic',
|
|
176
|
+
input: ({ context }) => ({ orderId: context.orderId! }),
|
|
177
|
+
onDone: {
|
|
178
|
+
target: 'done',
|
|
179
|
+
actions: assign(({ event }) => ({ txnId: event.output.txnId })),
|
|
180
|
+
},
|
|
181
|
+
onError: {
|
|
182
|
+
target: 'failed',
|
|
183
|
+
actions: assign(({ event }) => ({ error: String(event.error) })),
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
on: {
|
|
187
|
+
'flow.cancel': 'cancelled',
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
done: { type: 'final' },
|
|
191
|
+
failed: {},
|
|
192
|
+
cancelled: {},
|
|
193
|
+
},
|
|
194
|
+
});
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Adapt the skeleton to domain events and actor topology; keep contracts and state semantics explicit.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "XState Actor Orchestration"
|
|
3
|
+
short_description: "Design and implement advanced XState actor systems"
|
|
4
|
+
default_prompt: "Use $xstate-actor-orchestration to model and implement this interaction flow with receptionist and orchestrator actor patterns."
|
|
File without changes
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Actor System Patterns
|
|
2
|
+
|
|
3
|
+
## 1. Orchestrator pattern
|
|
4
|
+
|
|
5
|
+
Use one actor as the policy owner for a workflow.
|
|
6
|
+
|
|
7
|
+
Responsibilities:
|
|
8
|
+
- Accept domain commands/events.
|
|
9
|
+
- Start/stop workers.
|
|
10
|
+
- Enforce timeout/retry/cancel policy.
|
|
11
|
+
- Translate worker outcomes into business states.
|
|
12
|
+
|
|
13
|
+
Do not put IO logic directly in orchestrator actions unless trivial.
|
|
14
|
+
|
|
15
|
+
## 2. Receptionist pattern in XState terms
|
|
16
|
+
|
|
17
|
+
In XState v5, this is implemented through actor-system registration and lookup:
|
|
18
|
+
- Register actors with `systemId`.
|
|
19
|
+
- Resolve actors via `system.get(systemId)` when direct refs are unavailable.
|
|
20
|
+
|
|
21
|
+
Use this when actors in different branches need late-bound communication.
|
|
22
|
+
|
|
23
|
+
## 3. Topology decision table
|
|
24
|
+
|
|
25
|
+
- Parent-child only:
|
|
26
|
+
- Use when communication is local and lifetime is tightly coupled.
|
|
27
|
+
- Receptionist lookup:
|
|
28
|
+
- Use when actor discovery must cross hierarchy boundaries.
|
|
29
|
+
- Event bus adapter actor:
|
|
30
|
+
- Use when integration requires protocol translation or fan-out.
|
|
31
|
+
|
|
32
|
+
## 4. Lifecycle guidance
|
|
33
|
+
|
|
34
|
+
- `invoke`:
|
|
35
|
+
- Prefer for state-bound tasks that should stop when exiting a state.
|
|
36
|
+
- `spawn`/`spawnChild`:
|
|
37
|
+
- Prefer for dynamic or longer-lived workers.
|
|
38
|
+
- Root actor:
|
|
39
|
+
- Own system-wide inspection and persistence boundaries.
|
|
40
|
+
|
|
41
|
+
## 5. Minimal receptionist example
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import { createMachine, createActor, sendTo } from 'xstate';
|
|
45
|
+
|
|
46
|
+
const workerMachine = createMachine({
|
|
47
|
+
id: 'worker',
|
|
48
|
+
initial: 'idle',
|
|
49
|
+
states: { idle: {} },
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const rootMachine = createMachine({
|
|
53
|
+
entry: ({ spawnChild }) => {
|
|
54
|
+
spawnChild(workerMachine, {
|
|
55
|
+
id: 'worker-local',
|
|
56
|
+
systemId: 'worker.service',
|
|
57
|
+
});
|
|
58
|
+
},
|
|
59
|
+
on: {
|
|
60
|
+
'task.dispatch': {
|
|
61
|
+
actions: sendTo(({ system }) => system.get('worker.service')!, {
|
|
62
|
+
type: 'task.run',
|
|
63
|
+
}),
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
createActor(rootMachine).start();
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Guard against missing registrations before `sendTo`.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Event Contract Rules
|
|
2
|
+
|
|
3
|
+
## Event naming
|
|
4
|
+
|
|
5
|
+
Use namespaced, domain-specific names:
|
|
6
|
+
- `checkout.submit`
|
|
7
|
+
- `payment.authorized`
|
|
8
|
+
- `payment.declined`
|
|
9
|
+
- `fulfillment.timeout`
|
|
10
|
+
|
|
11
|
+
Avoid generic names unless they are machine-internal and local.
|
|
12
|
+
|
|
13
|
+
Use consistent namespace depth per bounded context:
|
|
14
|
+
- `<domain>.<action>` for simple flows (`cart.add`).
|
|
15
|
+
- `<domain>.<subdomain>.<action>` for larger systems (`checkout.payment.authorize`).
|
|
16
|
+
|
|
17
|
+
## Event typing
|
|
18
|
+
|
|
19
|
+
Define discriminated unions and keep payloads explicit.
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
type CheckoutEvent =
|
|
23
|
+
| { type: 'checkout.submit'; cartId: string }
|
|
24
|
+
| { type: 'payment.authorized'; txnId: string }
|
|
25
|
+
| { type: 'payment.declined'; code: string; reason: string }
|
|
26
|
+
| { type: 'checkout.cancel' };
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
For wildcard routing, declare namespace fallback variants in machine transitions and keep explicit types for domain events.
|
|
30
|
+
|
|
31
|
+
## Command vs fact
|
|
32
|
+
|
|
33
|
+
- Command events request behavior (`checkout.submit`).
|
|
34
|
+
- Fact events report outcomes (`payment.authorized`).
|
|
35
|
+
|
|
36
|
+
Keep this distinction explicit to simplify orchestration.
|
|
37
|
+
|
|
38
|
+
## Wildcard routing patterns
|
|
39
|
+
|
|
40
|
+
Use wildcard transitions for orchestration and fallback handling:
|
|
41
|
+
- `payment.*` to handle payment namespace events.
|
|
42
|
+
- `checkout.*` to route checkout namespace events.
|
|
43
|
+
- `*` as global fallback.
|
|
44
|
+
|
|
45
|
+
Use exact matches for business-critical transitions and wildcard matches for coarse routing.
|
|
46
|
+
Exact transitions take precedence over wildcard transitions.
|
|
47
|
+
|
|
48
|
+
Example:
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
createMachine({
|
|
52
|
+
on: {
|
|
53
|
+
'checkout.submit': { target: '.submitting' },
|
|
54
|
+
'checkout.*': { actions: 'trackCheckoutNamespaceEvent' },
|
|
55
|
+
'payment.*': { actions: 'routePaymentNamespaceEvent' },
|
|
56
|
+
'*': { actions: 'trackUnhandledEvent' },
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Avoid putting domain success logic exclusively behind wildcard handlers.
|
|
62
|
+
|
|
63
|
+
## Error contract
|
|
64
|
+
|
|
65
|
+
Model expected business errors as typed events/states.
|
|
66
|
+
Use unexpected errors for fault handling paths.
|
|
67
|
+
|
|
68
|
+
## Versioning
|
|
69
|
+
|
|
70
|
+
When an event contract changes:
|
|
71
|
+
1. Add new event variant.
|
|
72
|
+
2. Support both versions temporarily in adapters.
|
|
73
|
+
3. Remove old variant after migration.
|
package/src/.agents/skills/xstate-actor-orchestration/references/functional-domain-patterns.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Functional Domain and Entity Transform Patterns
|
|
2
|
+
|
|
3
|
+
Use these rules for domain/entity object transformation code used by machines.
|
|
4
|
+
|
|
5
|
+
## Core rules
|
|
6
|
+
|
|
7
|
+
1. Keep transforms pure.
|
|
8
|
+
- Accept input data and return next data.
|
|
9
|
+
- Do not mutate input objects.
|
|
10
|
+
- Do not perform IO in transforms.
|
|
11
|
+
|
|
12
|
+
2. Keep transforms outside machine config where possible.
|
|
13
|
+
- Prefer `domain/` or `entities/` modules for reusable transform logic.
|
|
14
|
+
- Keep actions/guards small and orchestration-focused.
|
|
15
|
+
|
|
16
|
+
3. Prefer immutable updates.
|
|
17
|
+
- Return new objects/arrays.
|
|
18
|
+
- Keep output shape predictable and typed.
|
|
19
|
+
|
|
20
|
+
4. Prefer early returns over nested `if/else`.
|
|
21
|
+
- Exit quickly for invalid or terminal branches.
|
|
22
|
+
- Keep the main success path linear.
|
|
23
|
+
|
|
24
|
+
## Example
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
type Payment = { amount: number; currency: string; status: 'new' | 'authorized' };
|
|
28
|
+
|
|
29
|
+
export function authorizePayment(payment: Payment, limit: number): Payment {
|
|
30
|
+
if (payment.amount <= 0) return payment;
|
|
31
|
+
if (payment.amount > limit) return payment;
|
|
32
|
+
if (payment.status === 'authorized') return payment;
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
...payment,
|
|
36
|
+
status: 'authorized',
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Machine integration pattern
|
|
42
|
+
|
|
43
|
+
- Use machine actions to call pure transforms.
|
|
44
|
+
- Keep action code thin:
|
|
45
|
+
- Read current context.
|
|
46
|
+
- Call pure transform.
|
|
47
|
+
- Assign returned value.
|
|
48
|
+
|
|
49
|
+
## Testing expectations
|
|
50
|
+
|
|
51
|
+
- Unit test transform modules directly without actor runtime.
|
|
52
|
+
- Cover edge conditions first.
|
|
53
|
+
- Keep golden-path and failure-path tests explicit.
|
package/src/.agents/skills/xstate-actor-orchestration/references/machine-structure-and-tags.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Machine Structure and Tags
|
|
2
|
+
|
|
3
|
+
Use structure as the primary control-flow model.
|
|
4
|
+
|
|
5
|
+
## 1. Scope with nested states
|
|
6
|
+
|
|
7
|
+
- Use parent/child states to limit where events are handled.
|
|
8
|
+
- Keep transitions local to the smallest valid scope.
|
|
9
|
+
- Move shared transitions to parent states when behavior is intentionally shared.
|
|
10
|
+
|
|
11
|
+
## 2. Choose parallel vs sequential intentionally
|
|
12
|
+
|
|
13
|
+
- Use parallel states when regions are independent and can progress concurrently.
|
|
14
|
+
- Use sequential states when one stage must complete before another can start.
|
|
15
|
+
- Do not force sequential flow for unrelated concerns.
|
|
16
|
+
|
|
17
|
+
## 3. Model flow with states, not booleans
|
|
18
|
+
|
|
19
|
+
- Do not use boolean flags to represent machine mode (`isLoading`, `isSaving`, `hasError`).
|
|
20
|
+
- Represent each mode with explicit states/substates and tags.
|
|
21
|
+
- Keep booleans only for raw domain facts that do not encode control flow.
|
|
22
|
+
|
|
23
|
+
## 4. Use tags for declarative UI state selection
|
|
24
|
+
|
|
25
|
+
- Add tags for stable UI concerns (e.g., `busy`, `error`, `success`, `canRetry`).
|
|
26
|
+
- In React, derive render behavior from `snapshot.hasTag(...)` and selectors.
|
|
27
|
+
- Keep tags semantic and durable across refactors.
|
|
28
|
+
|
|
29
|
+
## 5. Namespace-aware routing strategy
|
|
30
|
+
|
|
31
|
+
- Prefer exact event transitions for business-critical behavior.
|
|
32
|
+
- Add namespace wildcards for orchestration routing:
|
|
33
|
+
- `billing.*`
|
|
34
|
+
- `checkout.*`
|
|
35
|
+
- `*` fallback
|
|
36
|
+
- Keep wildcard handlers observability-focused unless intentionally routing.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# React Container Pattern for XState
|
|
2
|
+
|
|
3
|
+
Use containers as controllers and components as pure render units.
|
|
4
|
+
|
|
5
|
+
## 1. Container responsibilities
|
|
6
|
+
|
|
7
|
+
- Create or receive actor refs.
|
|
8
|
+
- Read state/context via `useSelector`.
|
|
9
|
+
- Map selected values into stable component props.
|
|
10
|
+
- Wire event handlers that send events to actors.
|
|
11
|
+
|
|
12
|
+
## 2. Presentational component responsibilities
|
|
13
|
+
|
|
14
|
+
- Receive props only.
|
|
15
|
+
- Render UI only.
|
|
16
|
+
- Avoid actor imports and machine knowledge.
|
|
17
|
+
|
|
18
|
+
## 3. `useSelector` guidance
|
|
19
|
+
|
|
20
|
+
- Prefer narrow selectors to limit rerenders.
|
|
21
|
+
- Select tags and derived values, not whole snapshots.
|
|
22
|
+
- Keep selectors deterministic and side-effect free.
|
|
23
|
+
|
|
24
|
+
## 4. `emit` + `useEffect` for fire-and-forget UI actions
|
|
25
|
+
|
|
26
|
+
- Use machine `emit(...)` to publish imperative signals (toast, navigation, analytics).
|
|
27
|
+
- Subscribe in container `useEffect`.
|
|
28
|
+
- Trigger UI side effects from emitted events, not from render paths.
|
|
29
|
+
|
|
30
|
+
Example pattern:
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
const sub = actorRef.on('ui.toast', (event) => {
|
|
35
|
+
toast(event.message);
|
|
36
|
+
});
|
|
37
|
+
return () => sub.unsubscribe();
|
|
38
|
+
}, [actorRef]);
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## 5. Composition guidance
|
|
42
|
+
|
|
43
|
+
- Container composes presentational components from selected state/context.
|
|
44
|
+
- Keep props cohesive; avoid passing entire context objects by default.
|
|
45
|
+
- Compose feature UI from multiple containers if actor boundaries differ.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Reliability and Observability
|
|
2
|
+
|
|
3
|
+
## Retry and timeout policy
|
|
4
|
+
|
|
5
|
+
Represent policy as states, not hidden timers.
|
|
6
|
+
|
|
7
|
+
Common structure:
|
|
8
|
+
- `working`
|
|
9
|
+
- `retry_wait`
|
|
10
|
+
- `failed_transient`
|
|
11
|
+
- `failed_terminal`
|
|
12
|
+
|
|
13
|
+
Track attempt counts in context and cap retries.
|
|
14
|
+
|
|
15
|
+
## Persistence
|
|
16
|
+
|
|
17
|
+
Use persisted snapshots for resumable workflows:
|
|
18
|
+
- Capture via `actor.getPersistedSnapshot()`.
|
|
19
|
+
- Restore via `createActor(logic, { snapshot })`.
|
|
20
|
+
|
|
21
|
+
Use persistence when workflows must survive reload/restart.
|
|
22
|
+
|
|
23
|
+
## Inspection
|
|
24
|
+
|
|
25
|
+
Attach an inspector at root actor creation.
|
|
26
|
+
Listen for:
|
|
27
|
+
- `@xstate.actor`
|
|
28
|
+
- `@xstate.event`
|
|
29
|
+
- `@xstate.snapshot`
|
|
30
|
+
- `@xstate.microstep`
|
|
31
|
+
|
|
32
|
+
Use inspection for diagnostics and test assertions, not business decisions.
|
|
33
|
+
|
|
34
|
+
## Recovery design checklist
|
|
35
|
+
|
|
36
|
+
1. Can the same external side effect run twice safely?
|
|
37
|
+
2. Which state is safe to restore into?
|
|
38
|
+
3. What event can resume the workflow after restart?
|
|
39
|
+
4. Which failures are user-recoverable vs terminal?
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Skill Validation Without Python
|
|
2
|
+
|
|
3
|
+
Use this checklist when Python-based validation tooling is unavailable or undesired.
|
|
4
|
+
|
|
5
|
+
## Command
|
|
6
|
+
|
|
7
|
+
Run the shell validator from the skill root:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
./scripts/validate-skill.sh .
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## What the shell validator checks
|
|
14
|
+
|
|
15
|
+
1. `SKILL.md` exists and has valid frontmatter delimiters.
|
|
16
|
+
2. Frontmatter contains only `name` and `description`.
|
|
17
|
+
3. `name` follows skill naming constraints (`[a-z0-9-]`, max 64 chars).
|
|
18
|
+
4. Skill folder name matches frontmatter `name`.
|
|
19
|
+
5. `agents/openai.yaml` exists.
|
|
20
|
+
6. `default_prompt` exists and mentions `$<skill-name>`.
|
|
21
|
+
7. `assets/statecharts/` exists for Mermaid artifacts.
|
|
22
|
+
8. `scripts/create-statechart-artifact.sh` exists and is executable.
|
|
23
|
+
9. No unresolved TODO placeholders remain in checked files.
|
|
24
|
+
10. Every local `references/*.md` link in `SKILL.md` points to an existing file.
|
|
25
|
+
|
|
26
|
+
## Additional manual checks
|
|
27
|
+
|
|
28
|
+
1. Confirm `description` includes clear trigger contexts.
|
|
29
|
+
2. Confirm workflow steps are imperative and actionable.
|
|
30
|
+
3. Confirm references stay one level deep from `SKILL.md`.
|
|
31
|
+
4. Confirm examples reflect XState v5 APIs used by your codebase.
|
|
32
|
+
5. Confirm each proposed/updated machine includes a `.mmd` diagram and `.signoff.md` record.
|
|
33
|
+
6. Confirm sign-off status advances by workflow phase (`DRAFT` -> `PLANNED` -> `APPROVED`).
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Source Map
|
|
2
|
+
|
|
3
|
+
Use these sources in order, loading only what the task needs.
|
|
4
|
+
|
|
5
|
+
## Core docs (Mintlify set provided by user)
|
|
6
|
+
|
|
7
|
+
- Introduction: https://statelyai-xstate.mintlify.app/introduction
|
|
8
|
+
- Actors: https://statelyai-xstate.mintlify.app/concepts/actors
|
|
9
|
+
- Actions: https://statelyai-xstate.mintlify.app/guides/actions
|
|
10
|
+
- Error handling: https://statelyai-xstate.mintlify.app/guides/error-handling
|
|
11
|
+
- Transitions: https://statelyai-xstate.mintlify.app/concepts/transitions
|
|
12
|
+
- Hierarchical composition: https://statelyai-xstate.mintlify.app/guides/parent-child
|
|
13
|
+
- Parallel states: https://statelyai-xstate.mintlify.app/guides/parallel-states
|
|
14
|
+
- TypeScript: https://statelyai-xstate.mintlify.app/advanced/typescript
|
|
15
|
+
- Visualization: https://statelyai-xstate.mintlify.app/advanced/visualization
|
|
16
|
+
- Inspection: https://statelyai-xstate.mintlify.app/advanced/inspection
|
|
17
|
+
- Testing: https://statelyai-xstate.mintlify.app/advanced/testing
|
|
18
|
+
|
|
19
|
+
## Supplemental official docs (needed for receptionist/system patterns)
|
|
20
|
+
|
|
21
|
+
- System (actor registration and lookup): https://stately.ai/docs/system
|
|
22
|
+
- Invoke: https://stately.ai/docs/invoke
|
|
23
|
+
- Spawn: https://stately.ai/docs/spawn
|
|
24
|
+
- Transitions (wildcards): https://stately.ai/docs/transitions#wildcard-transitions
|
|
25
|
+
- Parent states: https://stately.ai/docs/parent-states
|
|
26
|
+
- Parallel states: https://stately.ai/docs/parallel-states
|
|
27
|
+
- Tags: https://stately.ai/docs/tags
|
|
28
|
+
- Event emitter (`emit`): https://stately.ai/docs/event-emitter
|
|
29
|
+
- React integration (`@xstate/react`, `useSelector`): https://stately.ai/docs/xstate-react
|
|
30
|
+
- Visualization: https://stately.ai/docs/visualization
|
|
31
|
+
- Persistence: https://stately.ai/docs/persistence
|
|
32
|
+
- Graph/path testing: https://stately.ai/docs/graph
|
|
33
|
+
- Migration notes: https://stately.ai/docs/migration
|
|
34
|
+
|
|
35
|
+
## Pattern context
|
|
36
|
+
|
|
37
|
+
- XState v5 launch article (mentions receptionist pattern and actor-system direction):
|
|
38
|
+
https://stately.ai/blog/2023-12-01-xstate-v5
|
|
39
|
+
|
|
40
|
+
## Loading guidance
|
|
41
|
+
|
|
42
|
+
1. Load only one section at a time based on current task.
|
|
43
|
+
2. Prefer API and concept docs over blog content for implementation details.
|
|
44
|
+
3. Use blog content for rationale and pattern naming only.
|
package/src/.agents/skills/xstate-actor-orchestration/references/statechart-review-and-signoff.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Statechart Review and Sign-Off
|
|
2
|
+
|
|
3
|
+
Use this process for every new machine proposal and every machine update.
|
|
4
|
+
|
|
5
|
+
This artifact is part of the compound workflow. Produce or update it in every phase, not only at the end.
|
|
6
|
+
|
|
7
|
+
## Required artifact bundle
|
|
8
|
+
|
|
9
|
+
For each machine change, create both files under `assets/statecharts/`:
|
|
10
|
+
- `<machine-name>-<timestamp>.mmd`
|
|
11
|
+
- `<machine-name>-<timestamp>.signoff.md`
|
|
12
|
+
|
|
13
|
+
Generate with:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
./scripts/create-statechart-artifact.sh . <machine-name>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Mermaid diagram requirements
|
|
20
|
+
|
|
21
|
+
Represent:
|
|
22
|
+
- Top-level states and nested states.
|
|
23
|
+
- Parallel regions where applicable.
|
|
24
|
+
- Key transitions, including wildcard routing (`domain.*`, `*`) when used.
|
|
25
|
+
- Terminal states and cancellation/failure paths.
|
|
26
|
+
- Tags that UI depends on (capture in sign-off notes if diagram labels become noisy).
|
|
27
|
+
|
|
28
|
+
## Review discussion checklist
|
|
29
|
+
|
|
30
|
+
1. Are scopes correct (events handled only where valid)?
|
|
31
|
+
2. Are parallel states used only for independent regions?
|
|
32
|
+
3. Are wildcard transitions fallback-oriented and not hiding core business flow?
|
|
33
|
+
4. Are retry/recovery states explicit?
|
|
34
|
+
5. Are UI-relevant tags represented and consistent with component selectors?
|
|
35
|
+
6. Are emitted imperative events (`emit`) intentional and documented?
|
|
36
|
+
|
|
37
|
+
## Phase-aware usage
|
|
38
|
+
|
|
39
|
+
1. Brainstorm phase
|
|
40
|
+
- Produce a draft `.mmd` artifact to compare options.
|
|
41
|
+
- Mark sign-off status as `DRAFT`.
|
|
42
|
+
|
|
43
|
+
2. Implementation-plan phase
|
|
44
|
+
- Update the same artifact line to the planned machine structure.
|
|
45
|
+
- Mark sign-off status as `PLANNED`.
|
|
46
|
+
- Capture unresolved decisions in review notes.
|
|
47
|
+
|
|
48
|
+
3. Implementation/delivery phase
|
|
49
|
+
- Update artifact to as-built machine behavior.
|
|
50
|
+
- Mark sign-off status as `APPROVED` when reviewed.
|
|
51
|
+
- Treat missing final artifact/sign-off as incomplete delivery.
|
|
52
|
+
|
|
53
|
+
## Final sign-off checklist
|
|
54
|
+
|
|
55
|
+
1. Diagram reflects current machine implementation.
|
|
56
|
+
2. Event namespace and wildcard behavior are reviewed.
|
|
57
|
+
3. Failure/cancel/recovery paths are reviewed.
|
|
58
|
+
4. Reviewer and date are recorded in `.signoff.md`.
|
|
59
|
+
5. Implementation is not marked complete until sign-off is present.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Testing Strategy
|
|
2
|
+
|
|
3
|
+
## Test layers
|
|
4
|
+
|
|
5
|
+
1. Unit tests:
|
|
6
|
+
- Actions, guards, pure transition logic.
|
|
7
|
+
|
|
8
|
+
2. Actor tests:
|
|
9
|
+
- Start actors, send events, assert snapshots and outputs.
|
|
10
|
+
|
|
11
|
+
3. Integration tests:
|
|
12
|
+
- Orchestrator plus real or fake worker actors.
|
|
13
|
+
|
|
14
|
+
4. Model/path tests:
|
|
15
|
+
- Generate critical paths from machine model.
|
|
16
|
+
|
|
17
|
+
## Priority scenarios
|
|
18
|
+
|
|
19
|
+
- Happy path completion.
|
|
20
|
+
- Cancellation at each in-flight stage.
|
|
21
|
+
- Retry exhaustion and terminal failure.
|
|
22
|
+
- Recovery from persisted snapshot.
|
|
23
|
+
- Out-of-order or duplicate events.
|
|
24
|
+
|
|
25
|
+
## Assertions to include
|
|
26
|
+
|
|
27
|
+
- Current state value.
|
|
28
|
+
- Context data invariants.
|
|
29
|
+
- Emitted events to collaborators.
|
|
30
|
+
- Invoked actor lifecycle (started/stopped as expected).
|
|
31
|
+
|
|
32
|
+
## Simulated time
|
|
33
|
+
|
|
34
|
+
Use simulated clocks for deterministic timeout testing.
|
|
35
|
+
Avoid wall-clock sleeps in tests.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
skill_dir="${1:-.}"
|
|
6
|
+
machine_name_raw="${2:-}"
|
|
7
|
+
timestamp="${3:-$(date '+%Y%m%d-%H%M%S')}"
|
|
8
|
+
phase="${4:-DRAFT}"
|
|
9
|
+
|
|
10
|
+
if [[ -z "$machine_name_raw" ]]; then
|
|
11
|
+
echo "Usage: $0 <skill-dir> <machine-name> [timestamp] [phase]" >&2
|
|
12
|
+
exit 1
|
|
13
|
+
fi
|
|
14
|
+
|
|
15
|
+
machine_name="$(echo "$machine_name_raw" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9]+/-/g; s/^-+//; s/-+$//')"
|
|
16
|
+
if [[ -z "$machine_name" ]]; then
|
|
17
|
+
echo "ERROR: machine-name must contain at least one alphanumeric character" >&2
|
|
18
|
+
exit 1
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
artifact_dir="$skill_dir/assets/statecharts"
|
|
22
|
+
mkdir -p "$artifact_dir"
|
|
23
|
+
|
|
24
|
+
artifact_base="${machine_name}-${timestamp}"
|
|
25
|
+
diagram_file="$artifact_dir/${artifact_base}.mmd"
|
|
26
|
+
signoff_file="$artifact_dir/${artifact_base}.signoff.md"
|
|
27
|
+
|
|
28
|
+
if [[ -e "$diagram_file" || -e "$signoff_file" ]]; then
|
|
29
|
+
echo "ERROR: Artifact already exists for ${artifact_base}" >&2
|
|
30
|
+
exit 1
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
cat > "$diagram_file" <<EOF
|
|
34
|
+
stateDiagram-v2
|
|
35
|
+
[*] --> "TODO: initial"
|
|
36
|
+
"TODO: initial" --> "TODO: next": "TODO: event"
|
|
37
|
+
"TODO: next" --> [*]
|
|
38
|
+
EOF
|
|
39
|
+
|
|
40
|
+
cat > "$signoff_file" <<EOF
|
|
41
|
+
# Statechart Sign-Off
|
|
42
|
+
|
|
43
|
+
- Machine: ${machine_name_raw}
|
|
44
|
+
- Artifact: ${artifact_base}
|
|
45
|
+
- Diagram: ./$(basename "$diagram_file")
|
|
46
|
+
- Source machine file: TODO:
|
|
47
|
+
|
|
48
|
+
## Change summary
|
|
49
|
+
|
|
50
|
+
TODO:
|
|
51
|
+
|
|
52
|
+
## Review discussion points
|
|
53
|
+
|
|
54
|
+
1. Scope and event visibility:
|
|
55
|
+
2. Parallel vs sequential structure:
|
|
56
|
+
3. Wildcard routing behavior:
|
|
57
|
+
4. Retry/cancel/recovery paths:
|
|
58
|
+
5. Tags used by UI selectors:
|
|
59
|
+
6. Emitted imperative events:
|
|
60
|
+
|
|
61
|
+
## Sign-off
|
|
62
|
+
|
|
63
|
+
- Status: ${phase}
|
|
64
|
+
- Reviewer:
|
|
65
|
+
- Date:
|
|
66
|
+
- Notes:
|
|
67
|
+
EOF
|
|
68
|
+
|
|
69
|
+
echo "Created:"
|
|
70
|
+
echo "- $diagram_file"
|
|
71
|
+
echo "- $signoff_file"
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
skill_dir="${1:-.}"
|
|
6
|
+
skill_md="$skill_dir/SKILL.md"
|
|
7
|
+
openai_yaml="$skill_dir/agents/openai.yaml"
|
|
8
|
+
statecharts_dir="$skill_dir/assets/statecharts"
|
|
9
|
+
statechart_script="$skill_dir/scripts/create-statechart-artifact.sh"
|
|
10
|
+
|
|
11
|
+
fail=0
|
|
12
|
+
|
|
13
|
+
ok() {
|
|
14
|
+
echo "OK: $1"
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
err() {
|
|
18
|
+
echo "ERROR: $1" >&2
|
|
19
|
+
fail=1
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if [[ ! -f "$skill_md" ]]; then
|
|
23
|
+
err "Missing SKILL.md at $skill_md"
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
if [[ ! -f "$openai_yaml" ]]; then
|
|
27
|
+
err "Missing agents/openai.yaml at $openai_yaml"
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
if [[ ! -d "$statecharts_dir" ]]; then
|
|
31
|
+
err "Missing statechart asset directory at $statecharts_dir"
|
|
32
|
+
else
|
|
33
|
+
ok "Statechart asset directory exists"
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
if [[ ! -f "$statechart_script" ]]; then
|
|
37
|
+
err "Missing statechart artifact script at $statechart_script"
|
|
38
|
+
elif [[ ! -x "$statechart_script" ]]; then
|
|
39
|
+
err "Statechart artifact script is not executable: $statechart_script"
|
|
40
|
+
else
|
|
41
|
+
ok "Statechart artifact script exists and is executable"
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
if [[ -f "$skill_md" ]]; then
|
|
45
|
+
first_line="$(head -n 1 "$skill_md" || true)"
|
|
46
|
+
if [[ "$first_line" != "---" ]]; then
|
|
47
|
+
err "SKILL.md must start with frontmatter delimiter '---'"
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
fm_end_line="$(awk 'NR > 1 && $0 == "---" { print NR; exit }' "$skill_md")"
|
|
51
|
+
if [[ -z "${fm_end_line:-}" ]]; then
|
|
52
|
+
err "SKILL.md is missing closing frontmatter delimiter '---'"
|
|
53
|
+
else
|
|
54
|
+
ok "Frontmatter delimiters found"
|
|
55
|
+
|
|
56
|
+
frontmatter="$(sed -n "2,$((fm_end_line - 1))p" "$skill_md")"
|
|
57
|
+
|
|
58
|
+
if ! grep -qE '^name:[[:space:]]*[^[:space:]].*$' <<<"$frontmatter"; then
|
|
59
|
+
err "Frontmatter must include non-empty 'name'"
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
if ! grep -qE '^description:[[:space:]]*[^[:space:]].*$' <<<"$frontmatter"; then
|
|
63
|
+
err "Frontmatter must include non-empty 'description'"
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
extra_keys="$(sed '/^[[:space:]]*$/d' <<<"$frontmatter" | sed 's/:.*$//' | grep -Ev '^(name|description)$' || true)"
|
|
67
|
+
if [[ -n "$extra_keys" ]]; then
|
|
68
|
+
err "Frontmatter contains unsupported key(s): $(tr '\n' ',' <<<"$extra_keys" | sed 's/,$//')"
|
|
69
|
+
else
|
|
70
|
+
ok "Frontmatter keys are limited to name and description"
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
skill_name="$(sed -n 's/^name:[[:space:]]*//p' <<<"$frontmatter" | head -n 1)"
|
|
74
|
+
if [[ ! "$skill_name" =~ ^[a-z0-9-]{1,64}$ ]]; then
|
|
75
|
+
err "name must match ^[a-z0-9-]{1,64}$ (found '$skill_name')"
|
|
76
|
+
else
|
|
77
|
+
ok "Skill name format is valid"
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
skill_dir_basename="$(basename "$skill_dir")"
|
|
81
|
+
if [[ "$skill_name" != "$skill_dir_basename" ]]; then
|
|
82
|
+
err "Folder name '$skill_dir_basename' must match frontmatter name '$skill_name'"
|
|
83
|
+
else
|
|
84
|
+
ok "Folder name matches frontmatter name"
|
|
85
|
+
fi
|
|
86
|
+
fi
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
if [[ -f "$openai_yaml" ]]; then
|
|
90
|
+
if ! grep -qE '^[[:space:]]*default_prompt:[[:space:]]*".*"$' "$openai_yaml"; then
|
|
91
|
+
err "agents/openai.yaml must include quoted default_prompt"
|
|
92
|
+
else
|
|
93
|
+
ok "default_prompt exists"
|
|
94
|
+
fi
|
|
95
|
+
|
|
96
|
+
if [[ -n "${skill_name:-}" ]] && ! grep -q '\$'"${skill_name}" "$openai_yaml"; then
|
|
97
|
+
err "default_prompt must mention \$${skill_name}"
|
|
98
|
+
elif [[ -n "${skill_name:-}" ]]; then
|
|
99
|
+
ok "default_prompt mentions $skill_name"
|
|
100
|
+
fi
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
if command -v rg >/dev/null 2>&1; then
|
|
104
|
+
set +e
|
|
105
|
+
rg -n '\[TODO|TODO:' \
|
|
106
|
+
"$skill_dir/SKILL.md" \
|
|
107
|
+
"$skill_dir/agents/openai.yaml" \
|
|
108
|
+
"$skill_dir/references" >/dev/null
|
|
109
|
+
todo_rc=$?
|
|
110
|
+
set -e
|
|
111
|
+
if [[ "$todo_rc" -eq 0 ]]; then
|
|
112
|
+
err "Unresolved TODO placeholders found in skill files"
|
|
113
|
+
elif [[ "$todo_rc" -eq 1 ]]; then
|
|
114
|
+
ok "No TODO markers found"
|
|
115
|
+
else
|
|
116
|
+
err "Failed to run TODO marker check with ripgrep"
|
|
117
|
+
fi
|
|
118
|
+
|
|
119
|
+
if [[ -f "$skill_md" ]]; then
|
|
120
|
+
while IFS= read -r rel_path; do
|
|
121
|
+
clean_path="${rel_path#references/}"
|
|
122
|
+
full_path="$skill_dir/references/$clean_path"
|
|
123
|
+
if [[ ! -f "$full_path" ]]; then
|
|
124
|
+
err "Missing reference file linked from SKILL.md: $rel_path"
|
|
125
|
+
fi
|
|
126
|
+
done < <(rg -o '\]\((references/[^)]+)\)' "$skill_md" | sed -E 's/.*\((references\/[^)]+)\).*/\1/' | sort -u)
|
|
127
|
+
ok "Reference links resolved"
|
|
128
|
+
fi
|
|
129
|
+
else
|
|
130
|
+
err "ripgrep (rg) is required for TODO and reference-link checks"
|
|
131
|
+
fi
|
|
132
|
+
|
|
133
|
+
if [[ "$fail" -ne 0 ]]; then
|
|
134
|
+
echo "Validation failed." >&2
|
|
135
|
+
exit 1
|
|
136
|
+
fi
|
|
137
|
+
|
|
138
|
+
echo "Validation passed."
|
package/src/AGENTS.md
CHANGED
|
@@ -136,13 +136,14 @@ worktree_bootstrap_notes:
|
|
|
136
136
|
|
|
137
137
|
- Commands: `.agents/commands/*.md` and `.agents/commands/workflow/*.md` (workflow namespace)
|
|
138
138
|
- Skills: `.agents/skills/*/SKILL.md`
|
|
139
|
+
- Skills may optionally include tool-specific agent metadata under `.agents/skills/*/agents/` (for example `openai.yaml`) when required by that skill's validator/runtime.
|
|
139
140
|
- References: `.agents/references/**`
|
|
140
141
|
- Agents: `.agents/agents/**/*.md`
|
|
141
142
|
|
|
142
143
|
## Implemented Components (Current Scope)
|
|
143
144
|
|
|
144
145
|
- Commands: `workflow:brainstorm`, `workflow:plan`, `workflow:work`, `workflow:triage`, `workflow:review`, `workflow:compound` (under `.agents/commands/workflow/`), plus `test-browser`, `metrics`, `assess`, `setup`, `sync` (root commands)
|
|
145
|
-
- Skills: `brainstorming`, `document-review`, `technical-review`, `compound-docs
|
|
146
|
+
- Skills: `brainstorming`, `document-review`, `technical-review`, `compound-docs` (alias: `compound_doc`), `file-todos`, `agent-browser`, `git-worktree`, `process-metrics`, `xstate-actor-orchestration`, `pii-protection-prisma`, `financial-workflow-integrity`, `audit-traceability`, `data-foundations`
|
|
146
147
|
- Agents:
|
|
147
148
|
- `repo-research-analyst`
|
|
148
149
|
- `learnings-researcher`
|
|
@@ -197,11 +198,12 @@ Maintenance:
|
|
|
197
198
|
| `brainstorming` | You need structured idea exploration and clarification without writing code. |
|
|
198
199
|
| `document-review` | You need to review a document/spec and extract issues, gaps, and concrete next actions. |
|
|
199
200
|
| `technical-review` | A plan or feature approach has passed document review and must be checked for technical correctness before build. |
|
|
200
|
-
| `compound-docs` | A durable learning (solved problem or implementation insight) should be captured as institutional knowledge. |
|
|
201
|
+
| `compound-docs` (alias: `compound_doc`) | A durable learning (solved problem or implementation insight) should be captured as institutional knowledge. |
|
|
201
202
|
| `file-todos` | You need a file-backed todo workflow for iterative multi-step changes. |
|
|
202
203
|
| `agent-browser` | You need to inspect available agents/skills and route deterministically. |
|
|
203
204
|
| `git-worktree` | You need isolated parallel work (review/feature) using git worktrees. |
|
|
204
205
|
| `process-metrics` | You want to log and assess session performance and process improvements. |
|
|
206
|
+
| `xstate-actor-orchestration` | You are evaluating complexity and need explicit state orchestration: React container-as-orchestrator for UI flows, or actor/state-machine orchestration for backend/internal workflows (especially multi-step async branching, retries/timeouts/cancellation, receptionist/child-actor coordination, or boolean-flag sprawl). |
|
|
205
207
|
|
|
206
208
|
### Reference standards (guardrails)
|
|
207
209
|
|