@chllming/wave-orchestration 0.8.0 → 0.8.1
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 +16 -0
- package/README.md +8 -8
- package/docs/plans/current-state.md +1 -1
- package/docs/plans/examples/wave-example-live-proof.md +1 -1
- package/docs/plans/migration.md +3 -3
- package/docs/reference/npmjs-trusted-publishing.md +2 -2
- package/docs/reference/sample-waves.md +4 -4
- package/package.json +1 -1
- package/releases/manifest.json +20 -0
- package/scripts/wave-orchestrator/coord-cli.mjs +6 -2
- package/scripts/wave-orchestrator/coordination-store.mjs +3 -1
- package/scripts/wave-orchestrator/routing-state.mjs +91 -4
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.8.1 - 2026-03-24
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- Updated the shipped package metadata, release manifest, README, migration guide, sample-wave docs, and npm publishing runbook to advertise `0.8.1` as the current release surface.
|
|
10
|
+
|
|
11
|
+
### Fixed And Hardened
|
|
12
|
+
|
|
13
|
+
- Helper-assignment policy resolution now treats `resolved-by-policy` follow-up as authoritative closure without requiring the original request to be rewritten.
|
|
14
|
+
- Manual `wave coord post --kind resolved-by-policy` now defaults to `status=resolved`, so operator-authored policy closures stop reopening the assignment they are meant to close.
|
|
15
|
+
- Multi-target helper requests now require assignment-specific policy evidence before closure, preventing one request-level `resolved-by-policy` note from accidentally closing sibling assignments.
|
|
16
|
+
|
|
17
|
+
### Testing And Validation
|
|
18
|
+
|
|
19
|
+
- Added regression coverage for default `resolved-by-policy` status handling and for multi-target assignment resolution that must not over-close sibling helper assignments.
|
|
20
|
+
|
|
5
21
|
## 0.8.0 - 2026-03-24
|
|
6
22
|
|
|
7
23
|
### Changed
|
package/README.md
CHANGED
|
@@ -79,18 +79,18 @@ Wave is built to mitigate those failures with a canonical authority set, generat
|
|
|
79
79
|
|
|
80
80
|
Current release:
|
|
81
81
|
|
|
82
|
-
- `@chllming/wave-orchestration@0.8.
|
|
83
|
-
- Release tag: [`v0.8.
|
|
82
|
+
- `@chllming/wave-orchestration@0.8.1`
|
|
83
|
+
- Release tag: [`v0.8.1`](https://github.com/chllming/agent-wave-orchestrator/releases/tag/v0.8.1)
|
|
84
84
|
- Public install path: npmjs
|
|
85
85
|
- Authenticated fallback: GitHub Packages
|
|
86
86
|
|
|
87
|
-
Highlights in `0.8.
|
|
87
|
+
Highlights in `0.8.1`:
|
|
88
88
|
|
|
89
|
-
-
|
|
90
|
-
-
|
|
91
|
-
-
|
|
92
|
-
- The
|
|
93
|
-
- Upgrade and operator docs now cover the full `0.8.
|
|
89
|
+
- `resolved-by-policy` helper follow-up now closes single-target helper assignments authoritatively instead of leaving stale helper-assignment barriers open.
|
|
90
|
+
- Manual `wave coord post --kind resolved-by-policy` now defaults to `status=resolved`, which matches the intended policy-closure semantics.
|
|
91
|
+
- Multi-target helper requests no longer over-close sibling assignments from a request-level policy note; assignment-specific evidence is required.
|
|
92
|
+
- The architecture-hardening migration plan, reducer or envelope wiring, and aligned docs or skills from the prior release remain intact.
|
|
93
|
+
- Upgrade and operator docs now cover the full `0.8.1` package surface end to end.
|
|
94
94
|
|
|
95
95
|
Requirements:
|
|
96
96
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Current State
|
|
2
2
|
|
|
3
|
-
- The starter workspace in this source repo reflects the `0.8.
|
|
3
|
+
- The starter workspace in this source repo reflects the `0.8.1` package release surface.
|
|
4
4
|
- The staged architecture cutover from launcher-centric decisions to reducer and phase-engine ownership is tracked in `docs/plans/architecture-hardening-migration.md`.
|
|
5
5
|
- The repository contains the published `@chllming/wave-orchestration` package plus the starter scaffold used by `wave init`.
|
|
6
6
|
- The runtime is package-first and non-destructive for adopting repos: `wave init --adopt-existing` records existing repo-owned plans, waves, prompts, and config without overwriting them, and `wave upgrade` writes only `.wave/install-state.json` plus `.wave/upgrade-history/`.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
This is a showcase-first sample wave.
|
|
4
4
|
|
|
5
|
-
Use it as the single reference example for the current `0.8.
|
|
5
|
+
Use it as the single reference example for the current `0.8.1` Wave surface.
|
|
6
6
|
|
|
7
7
|
It intentionally combines more sections than a normal production wave so one file can demonstrate:
|
|
8
8
|
|
package/docs/plans/migration.md
CHANGED
|
@@ -24,13 +24,13 @@ GitHub Packages remains available as an authenticated fallback path, and maintai
|
|
|
24
24
|
- Fresh `wave init` seeds the starter `skills/` library. `wave init --adopt-existing` records existing repo-owned skill bundles when they are already present, but does not replace or rewrite them.
|
|
25
25
|
- The current runtime expects the post-roadmap model: typed coordination, compiled inboxes, `A8` integration, staged closure, orchestrator-first clarification, and operational runtime policy.
|
|
26
26
|
|
|
27
|
-
## Upgrading From 0.6.x To 0.8.
|
|
27
|
+
## Upgrading From 0.6.x To 0.8.1
|
|
28
28
|
|
|
29
29
|
Read `CHANGELOG.md` first, then treat this section as the repo-owned migration checklist for adopted `0.6.x` workspaces.
|
|
30
30
|
|
|
31
31
|
`wave upgrade` updates the installed runtime only. It does not copy planner starter files into a repo that already owns its docs, skills, and Context7 bundles.
|
|
32
32
|
|
|
33
|
-
`0.8.
|
|
33
|
+
`0.8.1` carries forward the `0.8.0` architecture-hardening release surface and tightens helper-assignment closure handling: `resolved-by-policy` records now default to `resolved`, single-target helper requests can close from policy follow-up without mutating the original request, and multi-target helper requests only close from assignment-specific policy evidence so sibling assignments stay honest.
|
|
34
34
|
|
|
35
35
|
### Required Repo Changes
|
|
36
36
|
|
|
@@ -42,7 +42,7 @@ If the repo adopted Wave before the planner corpus became a tracked required sur
|
|
|
42
42
|
- `docs/reference/wave-planning-lessons.md`
|
|
43
43
|
- the `planner-agentic` bundle entry in `docs/context7/bundles.json`
|
|
44
44
|
|
|
45
|
-
If the repo copied the shipped starter architecture docs or skills and wants the `0.8.
|
|
45
|
+
If the repo copied the shipped starter architecture docs or skills and wants the `0.8.1` authority-model language, also sync:
|
|
46
46
|
|
|
47
47
|
- `docs/agents/wave-launcher-role.md`
|
|
48
48
|
- `docs/agents/wave-orchestrator-role.md`
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
This repo now includes a dedicated npmjs publish workflow at [publish-npm.yml](../../.github/workflows/publish-npm.yml).
|
|
4
4
|
|
|
5
|
-
The current `0.8.
|
|
5
|
+
The current `0.8.1` release procedure publishes through a repository Actions secret named `NPM_TOKEN`.
|
|
6
6
|
|
|
7
7
|
## What This Repo Already Does
|
|
8
8
|
|
|
@@ -47,6 +47,6 @@ If this repo later needs private npm dependencies during CI, consider a separate
|
|
|
47
47
|
1. Confirm [publish-npm.yml](../../.github/workflows/publish-npm.yml) is on the default branch.
|
|
48
48
|
2. Confirm `NPM_TOKEN` exists in the GitHub repo secrets.
|
|
49
49
|
3. Confirm the package version has been bumped and committed.
|
|
50
|
-
4. Push the release commit and release tag, for example `v0.8.
|
|
50
|
+
4. Push the release commit and release tag, for example `v0.8.1`.
|
|
51
51
|
5. Verify both `publish-npm.yml` and `publish-package.yml` start from the tag push.
|
|
52
52
|
6. Verify the npmjs publish completes successfully for the tagged source.
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "Sample Waves"
|
|
3
|
-
summary: "Showcase-first sample waves that demonstrate the current 0.8.
|
|
3
|
+
summary: "Showcase-first sample waves that demonstrate the current 0.8.1 Wave surface."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Sample Waves
|
|
7
7
|
|
|
8
|
-
This guide points to showcase-first sample waves that demonstrate the current `0.8.
|
|
8
|
+
This guide points to showcase-first sample waves that demonstrate the current `0.8.1` authored Wave surface.
|
|
9
9
|
|
|
10
10
|
The examples are intentionally denser than typical production waves. Their job is to teach the current authoring and runtime surface quickly, not to be the smallest possible launch-ready files.
|
|
11
11
|
|
|
@@ -15,7 +15,7 @@ The examples are intentionally denser than typical production waves. Their job i
|
|
|
15
15
|
Shows what a good `repo-landed` outcome looks like when one promoted component only closes honestly if desired-state records, reconcile-loop substrate, and cluster-view surfaces land together. It emphasizes maturity discipline, explicit deliverables, and shared-plan closure without drifting into `pilot-live` claims.
|
|
16
16
|
|
|
17
17
|
- [Full modern sample wave](../plans/examples/wave-example-live-proof.md)
|
|
18
|
-
Shows the combined `0.8.
|
|
18
|
+
Shows the combined `0.8.1` authored surface in one file: closure roles, `E0`, optional security review, delegated and pinned benchmark targets, richer executor config, `### Skills`, `### Capabilities`, `### Deliverables`, `### Exit contract`, `### Proof artifacts`, sticky retry, deploy environments, and proof-first live-wave structure.
|
|
19
19
|
|
|
20
20
|
## What These Examples Teach
|
|
21
21
|
|
|
@@ -38,7 +38,7 @@ The examples are intentionally denser than typical production waves. Their job i
|
|
|
38
38
|
|
|
39
39
|
## Feature Coverage Map
|
|
40
40
|
|
|
41
|
-
Together these samples cover the main surfaces added or hardened for `0.8.
|
|
41
|
+
Together these samples cover the main surfaces added or hardened for `0.8.1`:
|
|
42
42
|
|
|
43
43
|
- repo-landed maturity discipline and anti-overclaim framing
|
|
44
44
|
- explicit shared-plan closure for future-wave safety
|
package/package.json
CHANGED
package/releases/manifest.json
CHANGED
|
@@ -2,6 +2,26 @@
|
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"packageName": "@chllming/wave-orchestration",
|
|
4
4
|
"releases": [
|
|
5
|
+
{
|
|
6
|
+
"version": "0.8.1",
|
|
7
|
+
"date": "2026-03-24",
|
|
8
|
+
"summary": "Helper-assignment policy-closure hardening, multi-target assignment-safety repair, and 0.8.1 release-surface alignment.",
|
|
9
|
+
"features": [
|
|
10
|
+
"`resolved-by-policy` follow-up now closes single-target helper assignments authoritatively without forcing the original request record itself to be rewritten.",
|
|
11
|
+
"Manual `wave coord post --kind resolved-by-policy` now defaults to `status=resolved`, so operator-entered policy closures stop behaving like fresh open coordination records.",
|
|
12
|
+
"Multi-target helper requests now require assignment-specific policy evidence before closure, which prevents a request-level policy note from accidentally closing sibling assignments that were not actually completed.",
|
|
13
|
+
"Regression coverage now exercises default `resolved-by-policy` status handling and the multi-target helper-assignment over-closure edge case directly.",
|
|
14
|
+
"Shipped package metadata, README, migration guidance, sample-wave docs, and npm publishing instructions now point at the `0.8.1` release surface."
|
|
15
|
+
],
|
|
16
|
+
"manualSteps": [
|
|
17
|
+
"Run `pnpm exec wave doctor` and `pnpm exec wave launch --lane main --dry-run --no-dashboard` after upgrading so the repo validates against the `0.8.1` runtime and helper-assignment closure contract.",
|
|
18
|
+
"If an adopted repo fails `wave doctor` after the upgrade, sync the repo-owned planner starter surface (`docs/agents/wave-planner-role.md`, `skills/role-planner/`, `docs/context7/planner-agent/`, `docs/reference/wave-planning-lessons.md`, and the `planner-agentic` bundle entry) before relying on planner-aware validation.",
|
|
19
|
+
"If a repo carries custom operator docs for `wave coord post --kind resolved-by-policy`, update that guidance so policy-closure examples either omit `--status` or use `--status resolved` explicitly.",
|
|
20
|
+
"If an adopted repo copied the starter architecture docs or skill bundles, sync the updated role prompts, `skills/wave-core/`, runtime skills, and closure-role skills so local guidance matches the `0.8.1` authority model and helper-assignment behavior.",
|
|
21
|
+
"Review `docs/plans/architecture-hardening-migration.md` before continuing reducer-authoritative cutover work in repos that extend the shipped starter surface."
|
|
22
|
+
],
|
|
23
|
+
"breaking": false
|
|
24
|
+
},
|
|
5
25
|
{
|
|
6
26
|
"version": "0.8.0",
|
|
7
27
|
"date": "2026-03-24",
|
|
@@ -69,7 +69,7 @@ function parseArgs(argv) {
|
|
|
69
69
|
priority: "normal",
|
|
70
70
|
dependsOn: [],
|
|
71
71
|
artifactRefs: [],
|
|
72
|
-
status: "
|
|
72
|
+
status: "",
|
|
73
73
|
id: "",
|
|
74
74
|
to: "",
|
|
75
75
|
response: "",
|
|
@@ -309,6 +309,10 @@ function appendCoordinationStatusUpdate(logPath, record, status, options = {}) {
|
|
|
309
309
|
});
|
|
310
310
|
}
|
|
311
311
|
|
|
312
|
+
function defaultStatusForKind(kind) {
|
|
313
|
+
return String(kind || "").trim().toLowerCase() === "resolved-by-policy" ? "resolved" : "open";
|
|
314
|
+
}
|
|
315
|
+
|
|
312
316
|
function appendTriageEscalationUpdateIfPresent(lanePaths, waveNumber, record) {
|
|
313
317
|
const triagePath = coordinationTriagePath(lanePaths, waveNumber);
|
|
314
318
|
if (!fs.existsSync(triagePath) || record?.kind !== "human-escalation") {
|
|
@@ -436,7 +440,7 @@ export async function runCoordinationCli(argv) {
|
|
|
436
440
|
priority: options.priority,
|
|
437
441
|
dependsOn: options.dependsOn,
|
|
438
442
|
artifactRefs: options.artifactRefs,
|
|
439
|
-
status: options.status,
|
|
443
|
+
status: options.status || defaultStatusForKind(options.kind),
|
|
440
444
|
source: "agent",
|
|
441
445
|
});
|
|
442
446
|
console.log(JSON.stringify(record, null, 2));
|
|
@@ -88,7 +88,9 @@ export function normalizeCoordinationRecord(rawRecord, defaults = {}) {
|
|
|
88
88
|
const lane = normalizeString(rawRecord.lane || defaults.lane);
|
|
89
89
|
const wave = Number.parseInt(String(rawRecord.wave ?? defaults.wave ?? ""), 10);
|
|
90
90
|
const agentId = normalizeString(rawRecord.agentId || defaults.agentId);
|
|
91
|
-
const status = normalizeString(
|
|
91
|
+
const status = normalizeString(
|
|
92
|
+
rawRecord.status || defaults.status || (kind === "resolved-by-policy" ? "resolved" : "open"),
|
|
93
|
+
).toLowerCase();
|
|
92
94
|
const priority = normalizeString(rawRecord.priority || defaults.priority || "normal").toLowerCase();
|
|
93
95
|
const confidence = normalizeString(rawRecord.confidence || defaults.confidence || "medium").toLowerCase();
|
|
94
96
|
const createdAt = normalizeString(rawRecord.createdAt || defaults.createdAt || now);
|
|
@@ -155,6 +155,82 @@ function assignmentStateForRecord(record) {
|
|
|
155
155
|
return "open";
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
+
function recordText(record) {
|
|
159
|
+
return `${String(record?.summary || "")}\n${String(record?.detail || "")}`.trim().toLowerCase();
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function targetMatchesAgent(target, agentId) {
|
|
163
|
+
const normalizedTarget = String(target || "").trim();
|
|
164
|
+
const normalizedAgentId = String(agentId || "").trim();
|
|
165
|
+
if (!normalizedTarget || !normalizedAgentId) {
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
return normalizedTarget === normalizedAgentId || normalizedTarget === `agent:${normalizedAgentId}`;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function recordTargetsAgent(record, agentId) {
|
|
172
|
+
const normalizedAgentId = String(agentId || "").trim();
|
|
173
|
+
if (!normalizedAgentId) {
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
if (String(record?.agentId || "").trim() === normalizedAgentId) {
|
|
177
|
+
return true;
|
|
178
|
+
}
|
|
179
|
+
return Array.isArray(record?.targets)
|
|
180
|
+
? record.targets.some((target) => targetMatchesAgent(target, normalizedAgentId))
|
|
181
|
+
: false;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function requestResolutionForAssignment({
|
|
185
|
+
coordinationState,
|
|
186
|
+
requestRecord,
|
|
187
|
+
assignmentId,
|
|
188
|
+
assignedAgentId,
|
|
189
|
+
target,
|
|
190
|
+
}) {
|
|
191
|
+
const requestId = String(requestRecord?.id || "").trim();
|
|
192
|
+
if (!requestId) {
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
const requestIdLower = requestId.toLowerCase();
|
|
196
|
+
const assignmentIdLower = String(assignmentId || "").trim().toLowerCase();
|
|
197
|
+
const requestTargets = Array.isArray(requestRecord?.targets)
|
|
198
|
+
? requestRecord.targets.filter((entry) => String(entry || "").trim())
|
|
199
|
+
: [];
|
|
200
|
+
const requiresAssignmentSpecificMatch = requestTargets.length > 1;
|
|
201
|
+
const resolvedRecords = [...(coordinationState?.resolvedByPolicy || [])].reverse();
|
|
202
|
+
for (const record of resolvedRecords) {
|
|
203
|
+
const dependsOn = Array.isArray(record?.dependsOn)
|
|
204
|
+
? record.dependsOn.map((value) => String(value || "").trim().toLowerCase())
|
|
205
|
+
: [];
|
|
206
|
+
const assignmentDependsOnMatch = assignmentIdLower && dependsOn.includes(assignmentIdLower);
|
|
207
|
+
const requestDependsOnMatch = dependsOn.includes(requestIdLower);
|
|
208
|
+
if (assignmentDependsOnMatch || (!requiresAssignmentSpecificMatch && requestDependsOnMatch)) {
|
|
209
|
+
return record;
|
|
210
|
+
}
|
|
211
|
+
const closureCondition = String(record?.closureCondition || "").trim().toLowerCase();
|
|
212
|
+
const assignmentClosureMatch =
|
|
213
|
+
assignmentIdLower && closureCondition.includes(assignmentIdLower);
|
|
214
|
+
const requestClosureMatch = closureCondition.includes(requestIdLower);
|
|
215
|
+
if (
|
|
216
|
+
assignmentClosureMatch ||
|
|
217
|
+
(!requiresAssignmentSpecificMatch && requestClosureMatch)
|
|
218
|
+
) {
|
|
219
|
+
return record;
|
|
220
|
+
}
|
|
221
|
+
if (!recordTargetsAgent(record, assignedAgentId) && !targetMatchesAgent(target, record?.agentId)) {
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
const text = recordText(record);
|
|
225
|
+
const assignmentTextMatch = assignmentIdLower && text.includes(assignmentIdLower);
|
|
226
|
+
const requestTextMatch = text.includes(requestIdLower);
|
|
227
|
+
if (assignmentTextMatch || (!requiresAssignmentSpecificMatch && requestTextMatch)) {
|
|
228
|
+
return record;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
|
|
158
234
|
export function buildRequestAssignments({
|
|
159
235
|
coordinationState,
|
|
160
236
|
agents,
|
|
@@ -179,8 +255,18 @@ export function buildRequestAssignments({
|
|
|
179
255
|
}
|
|
180
256
|
for (const target of targets) {
|
|
181
257
|
const resolution = resolveTargetAssignment(target, agents, ledger, capabilityRouting);
|
|
258
|
+
const assignmentId = `assignment:${record.id}:${targetSlug(target) || "target"}`;
|
|
259
|
+
const resolvedByPolicyRecord = requestResolutionForAssignment({
|
|
260
|
+
coordinationState,
|
|
261
|
+
requestRecord: record,
|
|
262
|
+
assignmentId,
|
|
263
|
+
assignedAgentId: resolution.assignedAgentId,
|
|
264
|
+
target,
|
|
265
|
+
});
|
|
266
|
+
const resolvedByPolicy = Boolean(resolvedByPolicyRecord);
|
|
267
|
+
const effectiveStatus = resolvedByPolicy ? "resolved" : record.status;
|
|
182
268
|
assignments.push({
|
|
183
|
-
id:
|
|
269
|
+
id: assignmentId,
|
|
184
270
|
requestId: record.id,
|
|
185
271
|
recordId: record.id,
|
|
186
272
|
sourceKind: record.kind,
|
|
@@ -188,20 +274,21 @@ export function buildRequestAssignments({
|
|
|
188
274
|
summary: record.summary || "",
|
|
189
275
|
detail: record.detail || "",
|
|
190
276
|
priority: record.priority || "normal",
|
|
191
|
-
requestStatus:
|
|
192
|
-
state: assignmentStateForRecord(record),
|
|
277
|
+
requestStatus: effectiveStatus,
|
|
278
|
+
state: assignmentStateForRecord({ ...record, status: effectiveStatus }),
|
|
193
279
|
target: resolution.target,
|
|
194
280
|
targetType: resolution.targetType,
|
|
195
281
|
capability: resolution.capability,
|
|
196
282
|
assignedAgentId: resolution.assignedAgentId,
|
|
197
283
|
assignmentReason: resolution.assignmentReason,
|
|
198
284
|
assignmentDetail: resolution.detail,
|
|
199
|
-
blocking: isOpenCoordinationStatus(record.status),
|
|
285
|
+
blocking: !resolvedByPolicy && isOpenCoordinationStatus(record.status),
|
|
200
286
|
artifactRefs: Array.isArray(record.artifactRefs) ? record.artifactRefs : [],
|
|
201
287
|
dependsOn: Array.isArray(record.dependsOn) ? record.dependsOn : [],
|
|
202
288
|
closureCondition: String(record.closureCondition || ""),
|
|
203
289
|
createdAt: record.createdAt,
|
|
204
290
|
updatedAt: record.updatedAt,
|
|
291
|
+
resolvedByRecordId: resolvedByPolicyRecord?.id || null,
|
|
205
292
|
});
|
|
206
293
|
}
|
|
207
294
|
}
|