create-harness-vibe-coding 0.8.17 → 0.8.18
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/CHANGELOG.md +9 -0
- package/README-CN.md +2 -0
- package/README.md +2 -0
- package/package.json +1 -1
- package/src/generator.js +613 -97
- package/src/index.js +173 -42
- package/src/prompts.js +18 -0
- package/templates/common/.claude/commands/wf-command-create.md +58 -0
- package/templates/common/.claude/commands/wf-help.md +4 -0
- package/templates/common/.claude/commands/wf-task-archive.md +26 -0
- package/templates/common/.claude/commands/wf-task-list.md +24 -0
- package/templates/common/.claude/commands/wf-task-record.md +24 -0
- package/templates/common/.claude/rules/ecc/common.md +1 -1
- package/templates/common/.claude/skills/wf-agents-docs/SKILL.md +15 -30
- package/templates/common/.claude/skills/wf-command-create/SKILL.md +37 -0
- package/templates/common/.claude/skills/wf-max/SKILL.md +1 -1
- package/templates/common/.claude/skills/wf-review/SKILL.md +29 -2
- package/templates/common/.claude/skills/wf-task-archive/SKILL.md +28 -0
- package/templates/common/.claude/skills/wf-task-list/SKILL.md +28 -0
- package/templates/common/.claude/skills/wf-task-record/SKILL.md +28 -0
- package/templates/common/.harness-version +66 -32
- package/templates/common/.opencode/commands/wf-command-create.md +61 -0
- package/templates/common/.opencode/commands/wf-help.md +4 -0
- package/templates/common/.opencode/commands/wf-task-archive.md +29 -0
- package/templates/common/.opencode/commands/wf-task-list.md +27 -0
- package/templates/common/.opencode/commands/wf-task-record.md +27 -0
- package/templates/common/CLAUDE.md +8 -6
- package/templates/common/Harness/MEMORY.md +9 -0
- package/templates/common/Harness/README.md +17 -36
- package/templates/common/Harness/ownership.manifest.json +87 -2
- package/templates/common/Harness/scripts/task-state.mjs +395 -5
- package/templates/common/Harness/scripts/validate-harness.mjs +411 -46
- package/templates/common/Harness/scripts/wf-remove.mjs +34 -2
- package/templates/common/Harness/specs/guides/SETUP.md +8 -0
- package/templates/common/Harness/specs/protocols/MEMORY_PROTOCOL.md +15 -0
- package/templates/common/Harness/specs/protocols/TASK_ARCHIVE.md +9 -3
- package/templates/common/Harness/specs/runtime/command-surface.json +215 -0
- package/templates/common/Harness/specs/runtime/subagents.md +6 -0
- package/templates/common/Harness/specs/workflows/WF-MAX.md +5 -0
- package/templates/common/Harness/specs/workflows/WF-STATE.md +66 -0
- package/templates/common/Harness/tasks/_template/STATE.json +6 -0
|
@@ -10,6 +10,21 @@ Memory is downstream of evidence. It records reusable patterns, not raw transcri
|
|
|
10
10
|
- **L2 = Startup Digest**: `Harness/memory/startup-hints.md`. Lightweight hints loaded at session start. Not a replacement for full router.
|
|
11
11
|
- **L3 = Detailed Durable Memory**: `Harness/memory/*.md` files. Loaded only when scenario matches via `routes.md`.
|
|
12
12
|
|
|
13
|
+
## Project/Global Memory Boundary
|
|
14
|
+
|
|
15
|
+
- `Harness/tasks/` and `Harness/PROGRESS.md` are always project-local, even when the Harness runtime is installed globally.
|
|
16
|
+
- Project memory lives in `Harness/memory/` and records repo-specific lessons, preferences, and tool patterns.
|
|
17
|
+
- Global memory may live under the selected global Harness directory for cross-project lessons and preferences.
|
|
18
|
+
- Global memory must never store project task state, secrets, raw transcripts, or private project facts.
|
|
19
|
+
|
|
20
|
+
## Project/Global Settings Boundary
|
|
21
|
+
|
|
22
|
+
- Project settings live in `Harness/settings.json` and override global settings.
|
|
23
|
+
- Global settings defaults live in the selected global Harness runtime under `Harness/settings.json`.
|
|
24
|
+
- Host-global settings are copied, not symlinked, into Claude Code, Codex, and OpenCode user config directories.
|
|
25
|
+
- Settings and memory must never store secrets; use external secret stores or environment variables.
|
|
26
|
+
- Existing user-authored config, command, skill, or agent files are user-owned unless they carry a Harness ownership marker.
|
|
27
|
+
|
|
13
28
|
## When To Write Memory
|
|
14
29
|
|
|
15
30
|
Write memory when any condition applies:
|
|
@@ -46,15 +46,21 @@ machine state.
|
|
|
46
46
|
- Do NOT delete historical evidence.
|
|
47
47
|
- `Harness/PROGRESS.md` keeps the last 5 non-archived task entries in the Task
|
|
48
48
|
Index.
|
|
49
|
-
- When outer task capsules exceed 5 completed/abandoned/obsolete tasks,
|
|
50
|
-
the
|
|
49
|
+
- When outer task capsules exceed 5 completed/abandoned/obsolete tasks, remind
|
|
50
|
+
the user to run the task archive command. Do not auto-archive during unrelated
|
|
51
|
+
validation or closeout unless the user explicitly invokes archive apply mode.
|
|
51
52
|
- The validator (`Harness/scripts/validate-harness.mjs`) warns when
|
|
52
53
|
`Harness/tasks/` holds more than 5 outer task capsules (excluding `_archive`,
|
|
53
54
|
`_template`, `auto`) and fails in `--strict` mode.
|
|
54
55
|
|
|
55
56
|
## Script
|
|
56
57
|
|
|
57
|
-
|
|
58
|
+
User-facing command:
|
|
59
|
+
|
|
60
|
+
- Codex: `$wf-task-archive` or `/skills wf-task-archive`.
|
|
61
|
+
- Claude Code/OpenCode: `/wf-task-archive`.
|
|
62
|
+
|
|
63
|
+
Underlying implementation: `Harness/scripts/task-state.mjs archive`.
|
|
58
64
|
|
|
59
65
|
- Default: dry-run.
|
|
60
66
|
- `--apply` to execute.
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"commands": [
|
|
4
|
+
{
|
|
5
|
+
"id": "wf-help",
|
|
6
|
+
"classification": "direct",
|
|
7
|
+
"aliases": ["/wf-help", "$wf-help", "/skills wf-help"],
|
|
8
|
+
"entersWf": false,
|
|
9
|
+
"taskCapsulePolicy": "none",
|
|
10
|
+
"surfaces": {
|
|
11
|
+
"claudeCommand": true,
|
|
12
|
+
"opencodeCommand": true,
|
|
13
|
+
"claudeSkill": true,
|
|
14
|
+
"codexSkill": true,
|
|
15
|
+
"helpRow": true
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"id": "wf",
|
|
20
|
+
"classification": "workflow",
|
|
21
|
+
"aliases": ["/wf", "$wf", "/skills wf"],
|
|
22
|
+
"entersWf": true,
|
|
23
|
+
"taskCapsulePolicy": "required",
|
|
24
|
+
"surfaces": {
|
|
25
|
+
"claudeCommand": true,
|
|
26
|
+
"opencodeCommand": true,
|
|
27
|
+
"claudeSkill": true,
|
|
28
|
+
"codexSkill": true,
|
|
29
|
+
"helpRow": true
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"id": "wf-max",
|
|
34
|
+
"classification": "workflow",
|
|
35
|
+
"aliases": ["/wf-max", "$wf-max", "/skills wf-max"],
|
|
36
|
+
"entersWf": true,
|
|
37
|
+
"taskCapsulePolicy": "required",
|
|
38
|
+
"surfaces": {
|
|
39
|
+
"claudeCommand": true,
|
|
40
|
+
"opencodeCommand": true,
|
|
41
|
+
"claudeSkill": true,
|
|
42
|
+
"codexSkill": true,
|
|
43
|
+
"helpRow": true
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"id": "wf-auto",
|
|
48
|
+
"classification": "workflow",
|
|
49
|
+
"aliases": ["/wf-auto", "$wf-auto", "/skills wf-auto"],
|
|
50
|
+
"entersWf": true,
|
|
51
|
+
"taskCapsulePolicy": "auto-capsule-required",
|
|
52
|
+
"surfaces": {
|
|
53
|
+
"claudeCommand": true,
|
|
54
|
+
"opencodeCommand": true,
|
|
55
|
+
"claudeSkill": true,
|
|
56
|
+
"codexSkill": true,
|
|
57
|
+
"helpRow": true
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"id": "wf-auto-spark",
|
|
62
|
+
"classification": "workflow",
|
|
63
|
+
"aliases": ["/wf-auto-spark", "$wf-auto-spark", "/skills wf-auto-spark"],
|
|
64
|
+
"entersWf": true,
|
|
65
|
+
"taskCapsulePolicy": "auto-capsule-required",
|
|
66
|
+
"surfaces": {
|
|
67
|
+
"claudeCommand": true,
|
|
68
|
+
"opencodeCommand": true,
|
|
69
|
+
"claudeSkill": true,
|
|
70
|
+
"codexSkill": true,
|
|
71
|
+
"helpRow": true
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"id": "wf-review",
|
|
76
|
+
"classification": "workflow",
|
|
77
|
+
"aliases": ["/wf-review", "$wf-review", "/skills wf-review"],
|
|
78
|
+
"entersWf": true,
|
|
79
|
+
"taskCapsulePolicy": "use-current-or-create-when-needed",
|
|
80
|
+
"surfaces": {
|
|
81
|
+
"claudeCommand": true,
|
|
82
|
+
"opencodeCommand": true,
|
|
83
|
+
"claudeSkill": true,
|
|
84
|
+
"codexSkill": true,
|
|
85
|
+
"helpRow": true
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"id": "wf-learn",
|
|
90
|
+
"classification": "workflow",
|
|
91
|
+
"aliases": ["/wf-learn", "$wf-learn", "/skills wf-learn"],
|
|
92
|
+
"entersWf": true,
|
|
93
|
+
"taskCapsulePolicy": "use-current-or-create-when-needed",
|
|
94
|
+
"surfaces": {
|
|
95
|
+
"claudeCommand": true,
|
|
96
|
+
"opencodeCommand": true,
|
|
97
|
+
"claudeSkill": true,
|
|
98
|
+
"codexSkill": true,
|
|
99
|
+
"helpRow": true
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"id": "wf-browser",
|
|
104
|
+
"classification": "workflow",
|
|
105
|
+
"aliases": ["/wf-browser", "$wf-browser", "/skills wf-browser"],
|
|
106
|
+
"entersWf": true,
|
|
107
|
+
"taskCapsulePolicy": "required",
|
|
108
|
+
"surfaces": {
|
|
109
|
+
"claudeCommand": true,
|
|
110
|
+
"opencodeCommand": true,
|
|
111
|
+
"claudeSkill": true,
|
|
112
|
+
"codexSkill": true,
|
|
113
|
+
"helpRow": true
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"id": "wf-readme",
|
|
118
|
+
"classification": "workflow",
|
|
119
|
+
"aliases": ["/wf-readme", "$wf-readme", "/skills wf-readme"],
|
|
120
|
+
"entersWf": true,
|
|
121
|
+
"taskCapsulePolicy": "required",
|
|
122
|
+
"surfaces": {
|
|
123
|
+
"claudeCommand": true,
|
|
124
|
+
"opencodeCommand": true,
|
|
125
|
+
"claudeSkill": true,
|
|
126
|
+
"codexSkill": true,
|
|
127
|
+
"helpRow": true
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"id": "wf-update",
|
|
132
|
+
"classification": "direct",
|
|
133
|
+
"aliases": ["/wf-update", "$wf-update", "/skills wf-update"],
|
|
134
|
+
"entersWf": false,
|
|
135
|
+
"taskCapsulePolicy": "none",
|
|
136
|
+
"surfaces": {
|
|
137
|
+
"claudeCommand": true,
|
|
138
|
+
"opencodeCommand": true,
|
|
139
|
+
"claudeSkill": true,
|
|
140
|
+
"codexSkill": true,
|
|
141
|
+
"helpRow": true
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
"id": "wf-remove",
|
|
146
|
+
"classification": "workflow",
|
|
147
|
+
"aliases": ["/wf-remove", "$wf-remove", "/skills wf-remove"],
|
|
148
|
+
"entersWf": true,
|
|
149
|
+
"taskCapsulePolicy": "required",
|
|
150
|
+
"surfaces": {
|
|
151
|
+
"claudeCommand": true,
|
|
152
|
+
"opencodeCommand": true,
|
|
153
|
+
"claudeSkill": true,
|
|
154
|
+
"codexSkill": true,
|
|
155
|
+
"helpRow": true
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
"id": "wf-task-record",
|
|
160
|
+
"classification": "direct",
|
|
161
|
+
"aliases": ["/wf-task-record", "$wf-task-record", "/skills wf-task-record"],
|
|
162
|
+
"entersWf": false,
|
|
163
|
+
"taskCapsulePolicy": "creates-or-updates",
|
|
164
|
+
"surfaces": {
|
|
165
|
+
"claudeCommand": true,
|
|
166
|
+
"opencodeCommand": true,
|
|
167
|
+
"claudeSkill": true,
|
|
168
|
+
"codexSkill": true,
|
|
169
|
+
"helpRow": true
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
"id": "wf-task-list",
|
|
174
|
+
"classification": "direct",
|
|
175
|
+
"aliases": ["/wf-task-list", "$wf-task-list", "/skills wf-task-list"],
|
|
176
|
+
"entersWf": false,
|
|
177
|
+
"taskCapsulePolicy": "none",
|
|
178
|
+
"surfaces": {
|
|
179
|
+
"claudeCommand": true,
|
|
180
|
+
"opencodeCommand": true,
|
|
181
|
+
"claudeSkill": true,
|
|
182
|
+
"codexSkill": true,
|
|
183
|
+
"helpRow": true
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
"id": "wf-task-archive",
|
|
188
|
+
"classification": "direct",
|
|
189
|
+
"aliases": ["/wf-task-archive", "$wf-task-archive", "/skills wf-task-archive"],
|
|
190
|
+
"entersWf": false,
|
|
191
|
+
"taskCapsulePolicy": "none",
|
|
192
|
+
"surfaces": {
|
|
193
|
+
"claudeCommand": true,
|
|
194
|
+
"opencodeCommand": true,
|
|
195
|
+
"claudeSkill": true,
|
|
196
|
+
"codexSkill": true,
|
|
197
|
+
"helpRow": true
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
"id": "wf-command-create",
|
|
202
|
+
"classification": "direct",
|
|
203
|
+
"aliases": ["/wf-command-create", "$wf-command-create", "/skills wf-command-create"],
|
|
204
|
+
"entersWf": false,
|
|
205
|
+
"taskCapsulePolicy": "required",
|
|
206
|
+
"surfaces": {
|
|
207
|
+
"claudeCommand": true,
|
|
208
|
+
"opencodeCommand": true,
|
|
209
|
+
"claudeSkill": true,
|
|
210
|
+
"codexSkill": true,
|
|
211
|
+
"helpRow": true
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
]
|
|
215
|
+
}
|
|
@@ -208,6 +208,12 @@ independent same-runtime subagent context; for broad WF-MAX review, dispatch
|
|
|
208
208
|
agents report suggestions only. The controller accepts, rejects, or escalates
|
|
209
209
|
each finding and owns the final decision.
|
|
210
210
|
|
|
211
|
+
### OpenCode Reviewer Caveat
|
|
212
|
+
|
|
213
|
+
`opencode run --agent reviewer`: current installed `.opencode/agents/reviewer.md`
|
|
214
|
+
is `mode: subagent`; OpenCode falls back to the default agent. Probe before
|
|
215
|
+
claiming primary-runner review. Prefer same-runtime reviewer subagent fallback.
|
|
216
|
+
|
|
211
217
|
## Subagent Status Handling
|
|
212
218
|
|
|
213
219
|
| Status | Controller Action |
|
|
@@ -86,6 +86,11 @@ Every Worker dispatch or peer-CLI call must be bounded by the controller's comma
|
|
|
86
86
|
|
|
87
87
|
Record the channel actually used, command/tool form, timeout, exit status, and a <=250 token Evidence-Packet in the task capsule. Do not create ad hoc probe scripts or write peer-CLI output to `%TEMP%`; persistent evidence belongs only under the current task's `evidence/` directory when it is intentionally part of the task record.
|
|
88
88
|
|
|
89
|
+
### Peer CLI Output Contract
|
|
90
|
+
|
|
91
|
+
- `opencode run --agent reviewer`: installed agent is `mode: subagent` per `.opencode/agents/reviewer.md`. Do NOT claim primary-runner role use without a live probe.
|
|
92
|
+
- Parse JSON/JSONL peer CLI output: fail on empty/non-JSON, error events, budget errors, fallback warnings, or missing final model text.
|
|
93
|
+
|
|
89
94
|
## Parallelism Priority
|
|
90
95
|
|
|
91
96
|
1. Read-only exploration — max parallel, all readSets
|
|
@@ -82,6 +82,67 @@ Use `Harness/scripts/task-state.mjs` as the deterministic state writer:
|
|
|
82
82
|
Do not rely on prompt instructions alone to keep active task, task `STATE.json`,
|
|
83
83
|
task `PROGRESS.md`, and root `Harness/PROGRESS.md` synchronized.
|
|
84
84
|
|
|
85
|
+
## Links (Cross-Task Dependencies)
|
|
86
|
+
|
|
87
|
+
STATE.json `links` enables cross-task dependency resolution without reading
|
|
88
|
+
every task capsule:
|
|
89
|
+
|
|
90
|
+
| Field | Type | Description |
|
|
91
|
+
|-------|------|-------------|
|
|
92
|
+
| `links.dependsOn` | `string[]` | Task IDs this task depends on (blockers) |
|
|
93
|
+
| `links.blocks` | `string[]` | Task IDs this task blocks |
|
|
94
|
+
| `links.related` | `string[]` | Related task IDs (no dependency direction) |
|
|
95
|
+
|
|
96
|
+
When resolving `links.dependsOn`, the controller reads only the listed tasks'
|
|
97
|
+
STATE.json, not all task capsules. A task with unresolved dependsOn entries
|
|
98
|
+
should stay in the blocked queue until its dependencies resolve.
|
|
99
|
+
|
|
100
|
+
## Work Items (Parallel Dispatch)
|
|
101
|
+
|
|
102
|
+
STATE.json `workItems[]` enables fine-grained parallel dispatch tracking with
|
|
103
|
+
per-item dependencies:
|
|
104
|
+
|
|
105
|
+
| Field | Type | Description |
|
|
106
|
+
|-------|------|-------------|
|
|
107
|
+
| `id` | `string` | Unique item identifier |
|
|
108
|
+
| `status` | `string` | `pending`, `ready`, `running`, `done`, `blocked`, `skipped`, `failed` |
|
|
109
|
+
| `phase` | `string` | Phase this item belongs to |
|
|
110
|
+
| `dependsOn` | `string[]` | Item IDs this item depends on |
|
|
111
|
+
| `parallelGroup` | `string` | Group name for concurrent dispatch (optional) |
|
|
112
|
+
| `readSet` | `string[]` | Files/patterns the item may read |
|
|
113
|
+
| `writeSet` | `string[]` | Files/patterns the item may write |
|
|
114
|
+
| `agent` | `string` | Agent role assigned (optional) |
|
|
115
|
+
| `evidence` | `string` | Evidence path or summary (optional) |
|
|
116
|
+
| `next` | `string` | Next action after this item completes (optional) |
|
|
117
|
+
|
|
118
|
+
`workItems` is an additive array — it supplements the dispatchLedger and queues
|
|
119
|
+
for finer-grained tracking. The dispatchLedger remains the canonical record of
|
|
120
|
+
subagent dispatches.
|
|
121
|
+
|
|
122
|
+
## Open Tasks
|
|
123
|
+
|
|
124
|
+
"Open tasks" are non-archived task capsules with status one of:
|
|
125
|
+
`active`, `in_progress`, `running`, `pending`, `blocked`,
|
|
126
|
+
`needs-user-decision`.
|
|
127
|
+
|
|
128
|
+
The active pointer (`Harness/PROGRESS.md`) marks the single task the agent
|
|
129
|
+
should resume. Other open tasks remain visible in the Task Index but are not
|
|
130
|
+
automatically loaded.
|
|
131
|
+
|
|
132
|
+
## Queue Entry Normalization
|
|
133
|
+
|
|
134
|
+
Queues (`ready`, `running`, `blocked`, `done`) accept both plain string entries
|
|
135
|
+
and object entries. The normalization rules are backward-compatible:
|
|
136
|
+
|
|
137
|
+
- A plain string entry is treated as a task or dispatch item ID.
|
|
138
|
+
- An object entry may contain the same fields as a work item (`id`, `status`,
|
|
139
|
+
`dependsOn`, etc.) for richer inline tracking.
|
|
140
|
+
- `task-state.mjs` preserves both forms during reconcile — it does not coerce
|
|
141
|
+
objects to strings or vice versa.
|
|
142
|
+
|
|
143
|
+
This enables incremental adoption: existing STATE.json files with string-only
|
|
144
|
+
queues continue to work without changes.
|
|
145
|
+
|
|
85
146
|
## Resume Protocol
|
|
86
147
|
|
|
87
148
|
New window / session start:
|
|
@@ -99,6 +160,11 @@ New window / session start:
|
|
|
99
160
|
- Queues: ready (can dispatch immediately), running (awaiting results),
|
|
100
161
|
blocked (needs resolution), done.
|
|
101
162
|
- nextAction (what to do next).
|
|
163
|
+
- **links.dependsOn**: if non-empty, check whether any dependency tasks are
|
|
164
|
+
still open (their STATE.json has a non-archived status). Report blocked
|
|
165
|
+
dependencies to the user.
|
|
166
|
+
- **workItems[]**: if non-empty, inspect items with status `running` or
|
|
167
|
+
`ready` for parallel dispatch candidates.
|
|
102
168
|
4. Do NOT bulk-read `Harness/tasks/` to find context. Use the active pointer.
|
|
103
169
|
5. Direct simple tasks may skip STATE/PLAN/PROGRESS unless the user says
|
|
104
170
|
"continue"/"resume".
|
|
@@ -10,12 +10,18 @@
|
|
|
10
10
|
"activeQuestion": null,
|
|
11
11
|
"nextAction": "Define goal and acceptance criteria",
|
|
12
12
|
"acceptance": [],
|
|
13
|
+
"links": {
|
|
14
|
+
"dependsOn": [],
|
|
15
|
+
"blocks": [],
|
|
16
|
+
"related": []
|
|
17
|
+
},
|
|
13
18
|
"queues": {
|
|
14
19
|
"ready": [],
|
|
15
20
|
"running": [],
|
|
16
21
|
"blocked": [],
|
|
17
22
|
"done": []
|
|
18
23
|
},
|
|
24
|
+
"workItems": [],
|
|
19
25
|
"dispatchLedger": [],
|
|
20
26
|
"decisions": [],
|
|
21
27
|
"risks": [],
|