opencode-plugin-flow 4.3.7 → 4.3.8
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 +20 -0
- package/README.md +13 -6
- package/dist/adapters/opencode/tools.d.ts +75 -0
- package/dist/cli.js +202 -15
- package/dist/cli.js.map +2 -2
- package/dist/index.js +364 -32
- package/dist/index.js.map +5 -5
- package/dist/runtime/api.d.ts +58 -0
- package/dist/runtime/schema.d.ts +534 -0
- package/dist/runtime/transitions.d.ts +41 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -35,6 +35,12 @@ success | partial | blocked
|
|
|
35
35
|
## Scope
|
|
36
36
|
<owned slice: path set, module, command, risk lens, route, data range, or question set>
|
|
37
37
|
|
|
38
|
+
## Pass metadata
|
|
39
|
+
- Pass id: <stable pass id from the manifest>
|
|
40
|
+
- Manifest row id: <row id from the manifest>
|
|
41
|
+
- Depends on: <upstream row ids or "none">
|
|
42
|
+
- Write scope: <none | manager-serial | exact-path | isolated-worktree | mixed>
|
|
43
|
+
|
|
38
44
|
## Coverage
|
|
39
45
|
- Expected: <files, ranges, questions, commands, or findings assigned>
|
|
40
46
|
- Checked: <actual coverage, for example "12/12 files" or "command not run">
|
|
@@ -89,6 +95,11 @@ success | partial | blocked
|
|
|
89
95
|
## Scope
|
|
90
96
|
<claim ids, sources or commands checked, and the acceptance question>
|
|
91
97
|
|
|
98
|
+
## Pass metadata
|
|
99
|
+
- Pass id: <stable pass id from the manifest>
|
|
100
|
+
- Manifest row id: <row id from the manifest>
|
|
101
|
+
- Depends on: <upstream row ids or "none">
|
|
102
|
+
|
|
92
103
|
## Verdict per claim
|
|
93
104
|
- <claim id>: verdict=<supported | partly-supported | unsupported | source-not-found>
|
|
94
105
|
- claim: <claim text>
|
|
@@ -119,6 +130,12 @@ success | partial | blocked
|
|
|
119
130
|
## Scope
|
|
120
131
|
<isolated worktree or exact path-owned slice>
|
|
121
132
|
|
|
133
|
+
## Pass metadata
|
|
134
|
+
- Pass id: <stable pass id from the manifest>
|
|
135
|
+
- Manifest row id: <row id from the manifest>
|
|
136
|
+
- Depends on: <upstream row ids or "none">
|
|
137
|
+
- Write scope: <exact-path | isolated-worktree>
|
|
138
|
+
|
|
122
139
|
## Changed or proposed patch
|
|
123
140
|
- <path>: <what changed and why>
|
|
124
141
|
|
|
@@ -145,6 +162,32 @@ live-verified | test-verified | type-check-only | not-verified
|
|
|
145
162
|
|
|
146
163
|
The manager must inspect and validate any candidate patch before recording Flow
|
|
147
164
|
completion.
|
|
165
|
+
|
|
166
|
+
## Manager pass accounting record
|
|
167
|
+
|
|
168
|
+
The manager, not the worker, may carry compact records into
|
|
169
|
+
\`flow_feature_complete.orchestrationPasses\`. Use one record per material pass or
|
|
170
|
+
implementation decision; keep handoffs and long artifacts outside \`.flow/**\`.
|
|
171
|
+
|
|
172
|
+
\`\`\`json
|
|
173
|
+
{
|
|
174
|
+
"id": "stable-pass-id",
|
|
175
|
+
"kind": "discovery | audit | review | validation | verification | candidate | implementation-decision",
|
|
176
|
+
"decision": "serial | parallel | candidate-exact-path | candidate-worktree | tournament | skipped",
|
|
177
|
+
"decisionReason": "why this pass shape was chosen",
|
|
178
|
+
"modes": ["evidence"],
|
|
179
|
+
"workerCount": 1,
|
|
180
|
+
"candidateWorkerCount": 0,
|
|
181
|
+
"verifierWorkerCount": 0,
|
|
182
|
+
"sliceIds": ["manifest-row-id"],
|
|
183
|
+
"dependsOn": [],
|
|
184
|
+
"writeScope": "none | manager-serial | exact-path | isolated-worktree | mixed",
|
|
185
|
+
"handoffRefs": ["/tmp/flow-handoff.md"],
|
|
186
|
+
"verificationStatus": "not-needed | pending | passed | failed | mixed | downgraded",
|
|
187
|
+
"outcome": "accepted | rejected | partial | not-covered | superseded",
|
|
188
|
+
"synthesisRef": "/tmp/flow-synthesis.md"
|
|
189
|
+
}
|
|
190
|
+
\`\`\`
|
|
148
191
|
`;
|
|
149
192
|
|
|
150
193
|
// skills/flow/references/parallel-orchestration.md
|
|
@@ -197,6 +240,35 @@ Pass notes:
|
|
|
197
240
|
or exact non-overlapping path ownership. Patches stay proposals until the
|
|
198
241
|
manager inspects, merges or rejects, and validates.
|
|
199
242
|
|
|
243
|
+
## Implementation pass decision
|
|
244
|
+
|
|
245
|
+
Before implementing a broad, risky, or multi-target feature, record one manager
|
|
246
|
+
decision. This is required even when the answer is "stay serial"; the point is
|
|
247
|
+
to make the skipped parallelism visible instead of relying on memory.
|
|
248
|
+
|
|
249
|
+
Use one of these decisions:
|
|
250
|
+
|
|
251
|
+
- \`serial\`: the manager implements directly because slices overlap, the next
|
|
252
|
+
edit depends on one shared contract, or prompt/merge overhead would exceed the
|
|
253
|
+
value.
|
|
254
|
+
- \`candidate-exact-path\`: one or more candidate workers may edit exact
|
|
255
|
+
non-overlapping paths or modules named by the manager.
|
|
256
|
+
- \`candidate-worktree\`: one or more candidate workers may edit in isolated
|
|
257
|
+
worktrees, then the manager inspects and merges or rejects.
|
|
258
|
+
- \`tournament\`: several isolated candidate implementations compete for the same
|
|
259
|
+
outcome; the manager filters by tests, review, and source inspection before
|
|
260
|
+
accepting one.
|
|
261
|
+
- \`skipped\`: candidate workers were considered but rejected; include the reason,
|
|
262
|
+
such as shared fixtures, shared API contracts, unclear ownership, or no user
|
|
263
|
+
authorization for worker edits.
|
|
264
|
+
|
|
265
|
+
Record the decision in the pass manifest with a stable pass id,
|
|
266
|
+
\`decisionReason\`, \`writeScope\`, expected verification, and where any handoff or
|
|
267
|
+
synthesis artifact will live. If the feature completes, include the compact
|
|
268
|
+
record in the \`orchestrationPasses\` array of the \`flow_feature_complete\`
|
|
269
|
+
payload. The runtime stores only compact accounting; full worker handoffs stay
|
|
270
|
+
in manager-owned scratch files or the conversation.
|
|
271
|
+
|
|
200
272
|
## When to stay serial
|
|
201
273
|
|
|
202
274
|
- One file, command, or design question determines the next step.
|
|
@@ -272,6 +344,12 @@ schemas, docs, tests, commands, or artifacts to identify real slices. Keep the
|
|
|
272
344
|
immediate blocker local: do not delegate the question that determines whether
|
|
273
345
|
fan-out is even valid.
|
|
274
346
|
|
|
347
|
+
Treat orientation as uncertainty reduction. Resolve environment uncertainty by
|
|
348
|
+
inspecting the repo, running cheap commands, or assigning evidence workers; ask
|
|
349
|
+
the user only when the remaining specification uncertainty would make a wrong
|
|
350
|
+
slice expensive to undo. Do not split a vague goal into workers until the
|
|
351
|
+
candidate slices have concrete targets, dependencies, and verification signals.
|
|
352
|
+
|
|
275
353
|
## Stage 2 — Slice
|
|
276
354
|
|
|
277
355
|
Split along whichever axis keeps slices independent: modules or path sets,
|
|
@@ -279,14 +357,29 @@ route or endpoint groups, risk lenses, command surfaces, data ranges, or claim
|
|
|
279
357
|
sets. Each slice needs a one-line scope, expected coverage, and a defined
|
|
280
358
|
output the manager can check.
|
|
281
359
|
|
|
360
|
+
For implementation slices, also name dependencies and write ownership before
|
|
361
|
+
spawning. A real dependency edge means the later slice waits for a verified
|
|
362
|
+
handoff or manager synthesis from the earlier slice; a shared file, fixture,
|
|
363
|
+
schema, or public contract usually means the work should stay serial unless an
|
|
364
|
+
isolated worktree is used. The manifest owns those edges through \`dependsOn\`
|
|
365
|
+
and \`writeScope\`.
|
|
366
|
+
|
|
282
367
|
## Stage 3 — Manifest (the pre-fan-out coverage gate)
|
|
283
368
|
|
|
284
369
|
Before spawning, write a pass manifest: one row per slice, plus a totals check.
|
|
370
|
+
Give the pass a stable id so later handoffs, verifier claims, and completion
|
|
371
|
+
payloads can refer to the same work without replaying chat.
|
|
285
372
|
|
|
286
|
-
|
|
|
287
|
-
| --- | --- | --- | --- | --- |
|
|
288
|
-
|
|
|
289
|
-
|
|
|
373
|
+
| Row id | Slice scope | Expected coverage | Mode | Depends on | Write scope | Verification tier | Handoff ref | Verification status | Synthesis ref |
|
|
374
|
+
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
375
|
+
| \`runtime-read\` | \`src/core/**\` plus its tests | 14 files | \`evidence\` | none | none | accept locally | pending | pending | pending |
|
|
376
|
+
| \`release-read\` | release contract: CI workflows, \`package.json\`, changelog | 6 files | \`evidence\` | none | none | verify once | pending | pending | pending |
|
|
377
|
+
|
|
378
|
+
\`writeScope\` values in runtime accounting are \`none\`, \`manager-serial\`,
|
|
379
|
+
\`exact-path\`, \`isolated-worktree\`, or \`mixed\`. Use \`manager-serial\` for a
|
|
380
|
+
recorded serial implementation decision, \`exact-path\` for disjoint candidate
|
|
381
|
+
edits in one checkout, and \`isolated-worktree\` for candidate work that must be
|
|
382
|
+
merged back by the manager.
|
|
290
383
|
|
|
291
384
|
- Count the total work items when countable: files, modules, routes, commands,
|
|
292
385
|
rows, findings, screenshots, or claims. Confirm slice counts add back to the
|
|
@@ -295,11 +388,20 @@ Before spawning, write a pass manifest: one row per slice, plus a totals check.
|
|
|
295
388
|
"all changed files plus callers" or "all public commands plus release docs."
|
|
296
389
|
- Assign each slice's verification tier now (see Stage 6). Deciding where a
|
|
297
390
|
wrong claim is expensive belongs before handoffs arrive, not after.
|
|
391
|
+
- Record dependency edges now. A row may be spawned only after every \`depends on\`
|
|
392
|
+
row it names has returned a verified handoff or a manager synthesis that
|
|
393
|
+
explicitly settles the dependency.
|
|
298
394
|
- Fix the slice map centrally before spawning if the gate does not reconcile.
|
|
299
395
|
|
|
300
396
|
The manifest is also the accounting contract for the pass: N rows spawned means
|
|
301
397
|
N handoffs collected and checked in Stage 5 before anything is synthesized.
|
|
302
398
|
|
|
399
|
+
For implementation decisions, add a manifest row even when no worker is spawned:
|
|
400
|
+
\`kind=implementation-decision\`, \`decision=serial\` or \`decision=skipped\`,
|
|
401
|
+
\`workerCount=0\`, \`writeScope=manager-serial\`, and a concrete \`decisionReason\`.
|
|
402
|
+
This is how Flow distinguishes deliberate serial work from forgotten candidate
|
|
403
|
+
or verifier passes.
|
|
404
|
+
|
|
303
405
|
Write the manifest where it survives the pass: the conversation is enough for a
|
|
304
406
|
single bounded pass, but when a follow-up pass or a session resume is
|
|
305
407
|
plausible, persist it with the synthesis (Stage 7) so the accounting can be
|
|
@@ -312,8 +414,10 @@ Every worker prompt includes:
|
|
|
312
414
|
\`\`\`text
|
|
313
415
|
Overall goal, context only: <goal>
|
|
314
416
|
Mode: evidence | review | validation | audit | verifier | candidate-implementation
|
|
417
|
+
Pass id and manifest row id: <stable ids from the manifest>
|
|
315
418
|
Your exact slice: <paths, modules, command, claim ids, risk lens, or worktree>
|
|
316
419
|
Expected coverage: <count, paths, range, or complete question set>
|
|
420
|
+
Dependencies and write scope: <verified dependencies, if any; none | manager-serial | exact-path | isolated-worktree>
|
|
317
421
|
Do: <bounded actions>
|
|
318
422
|
Do not: call state-changing Flow tools, edit .flow/**, own sibling slices, or make the final Flow verdict.
|
|
319
423
|
Return only the Flow handoff in this exact shape:
|
|
@@ -339,6 +443,20 @@ worker that never returns, errors out, returns empty or unstructured output, or
|
|
|
339
443
|
reports \`partial\` or \`blocked\` is a hole in the pass, and synthesizing around it
|
|
340
444
|
silently drops a slice.
|
|
341
445
|
|
|
446
|
+
For each row, fill in:
|
|
447
|
+
|
|
448
|
+
- \`handoffRefs\`: worker ids, handoff file paths, command output artifacts, or
|
|
449
|
+
review packet location that the manager can re-open.
|
|
450
|
+
- \`verificationStatus\`: \`not-needed\`, \`pending\`, \`passed\`, \`failed\`, \`mixed\`,
|
|
451
|
+
or \`downgraded\`.
|
|
452
|
+
- \`outcome\`: \`accepted\`, \`rejected\`, \`partial\`, \`not-covered\`, or \`superseded\`.
|
|
453
|
+
- \`synthesisRef\`: the manager-owned synthesis file or plan field that carries
|
|
454
|
+
the accepted result forward.
|
|
455
|
+
|
|
456
|
+
Rows with no worker, such as serial or skipped implementation decisions, still
|
|
457
|
+
need a row id, decision, reason, and outcome. They are not handoffs, but they
|
|
458
|
+
are accounting.
|
|
459
|
+
|
|
342
460
|
Worker failure ladder:
|
|
343
461
|
|
|
344
462
|
1. Re-spawn once with a narrower slice and a note about what the first attempt
|
|
@@ -360,6 +478,11 @@ handoff only after a cheap manager-side pass:
|
|
|
360
478
|
- The evidence supports the claim, not just the topic.
|
|
361
479
|
- Findings stay inside the worker's slice.
|
|
362
480
|
- Headline counts can be recounted or traced.
|
|
481
|
+
- Dependency claims cite the verified upstream handoff, synthesis, or source
|
|
482
|
+
artifact they depend on.
|
|
483
|
+
- Candidate implementation claims identify whether they came from exact path
|
|
484
|
+
ownership or an isolated worktree, and whether the manager inspected the
|
|
485
|
+
resulting patch.
|
|
363
486
|
- Contradictions between workers are either resolved or explicitly marked as
|
|
364
487
|
contested.
|
|
365
488
|
|
|
@@ -424,6 +547,38 @@ Where accepted evidence goes:
|
|
|
424
547
|
- Candidate patches are not Flow evidence until the manager inspects, merges or
|
|
425
548
|
rejects them, and validates the main Flow-managed workspace.
|
|
426
549
|
|
|
550
|
+
When completing a feature, include compact pass accounting in
|
|
551
|
+
\`flow_feature_complete.orchestrationPasses\` for any pass or implementation
|
|
552
|
+
decision that materially affected the feature:
|
|
553
|
+
|
|
554
|
+
\`\`\`json
|
|
555
|
+
{
|
|
556
|
+
"id": "feature-id-implementation-decision",
|
|
557
|
+
"kind": "implementation-decision",
|
|
558
|
+
"decision": "serial",
|
|
559
|
+
"decisionReason": "Shared schema and tests made exact path ownership unsafe.",
|
|
560
|
+
"modes": [],
|
|
561
|
+
"workerCount": 0,
|
|
562
|
+
"candidateWorkerCount": 0,
|
|
563
|
+
"verifierWorkerCount": 0,
|
|
564
|
+
"sliceIds": ["manager-implementation"],
|
|
565
|
+
"dependsOn": [],
|
|
566
|
+
"writeScope": "manager-serial",
|
|
567
|
+
"handoffRefs": [],
|
|
568
|
+
"verificationStatus": "not-needed",
|
|
569
|
+
"outcome": "accepted",
|
|
570
|
+
"synthesisRef": "/tmp/flow-pass-synthesis.md"
|
|
571
|
+
}
|
|
572
|
+
\`\`\`
|
|
573
|
+
|
|
574
|
+
For candidate and verifier passes, use \`kind: "candidate"\` or
|
|
575
|
+
\`kind: "verification"\`, list the worker modes used, worker counts, slice ids,
|
|
576
|
+
handoff refs, dependency ids, verification status, and whether the manager
|
|
577
|
+
accepted, rejected, downgraded, or superseded the pass. The runtime aggregates
|
|
578
|
+
these compact records into \`session.budget.orchestration\` and stores them on
|
|
579
|
+
the feature history entry. Do not store full handoffs, long logs, or scratch
|
|
580
|
+
tables in \`.flow/session.json\`.
|
|
581
|
+
|
|
427
582
|
Persist the manifest and the synthesis when another pass may follow or the
|
|
428
583
|
session is long enough to be compacted or resumed: write the distilled result —
|
|
429
584
|
the accounted manifest, accepted claims with evidence and confidence, dropped
|
|
@@ -442,6 +597,10 @@ Stop after a pass when:
|
|
|
442
597
|
- accepted claims are evidenced, scoped, and confidence-labeled.
|
|
443
598
|
- material single-source, contested, high-stakes, or payload-bound claims have
|
|
444
599
|
been verified or downgraded.
|
|
600
|
+
- every dependency edge named in the manifest has either a verified upstream
|
|
601
|
+
result or an explicit not-covered outcome.
|
|
602
|
+
- implementation pass decisions are recorded, including skipped candidate
|
|
603
|
+
workers and the reason they were skipped.
|
|
445
604
|
- remaining gaps are explicit and do not block the Flow artifact being produced.
|
|
446
605
|
|
|
447
606
|
Start a bounded follow-up pass only when:
|
|
@@ -449,6 +608,9 @@ Start a bounded follow-up pass only when:
|
|
|
449
608
|
- the original slice map missed material scope.
|
|
450
609
|
- workers disagree on a claim that affects the Flow decision.
|
|
451
610
|
- a high-stakes or payload-bound claim needs verification.
|
|
611
|
+
- a dependency has just become verified and now unlocks a dependent slice.
|
|
612
|
+
- a candidate patch was rejected and an isolated alternative is still cheaper
|
|
613
|
+
than serial repair.
|
|
452
614
|
- a first pass exposes a narrower implementation or validation slice worth
|
|
453
615
|
isolating.
|
|
454
616
|
|
|
@@ -475,21 +637,24 @@ directory. The manager keeps the middleware local because it is one file and
|
|
|
475
637
|
anchors every other judgment.
|
|
476
638
|
|
|
477
639
|
Pass manifest: twelve countable route modules remain after the local check, and
|
|
478
|
-
4 + 3 + 5 adds back to 12 with no overlaps or gaps.
|
|
640
|
+
4 + 3 + 5 adds back to 12 with no overlaps or gaps. The pass id is
|
|
641
|
+
\`api-error-handling-read\`.
|
|
479
642
|
|
|
480
|
-
|
|
|
481
|
-
| --- | --- | --- | --- | --- |
|
|
482
|
-
|
|
|
483
|
-
|
|
|
484
|
-
|
|
|
643
|
+
| Row id | Slice scope | Expected coverage | Mode | Depends on | Write scope | Verification tier | Handoff ref | Verification status | Synthesis ref |
|
|
644
|
+
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
645
|
+
| \`routes-auth\` | auth and account routes | 4/12 modules | \`evidence\` | none | none | accept locally | pending | pending | pending |
|
|
646
|
+
| \`routes-billing\` | billing and subscription routes | 3/12 modules | \`review\` | none | none | verify once | pending | pending | pending |
|
|
647
|
+
| \`routes-admin\` | remaining content and admin routes | 5/12 modules | \`audit\` | none | none | verify once | pending | pending | pending |
|
|
485
648
|
|
|
486
649
|
Worker prompts:
|
|
487
650
|
|
|
488
651
|
\`\`\`text
|
|
489
652
|
Overall goal, context only: confirm API error handling is consistent.
|
|
490
653
|
Mode: evidence
|
|
654
|
+
Pass id and manifest row id: api-error-handling-read / routes-auth
|
|
491
655
|
Your exact slice: the four auth and account route modules under src/routes/.
|
|
492
656
|
Expected coverage: 4/4 modules.
|
|
657
|
+
Dependencies and write scope: none; none.
|
|
493
658
|
Do: report each route's error paths, status codes, and middleware usage with file:line evidence.
|
|
494
659
|
Do not: call state-changing Flow tools, edit .flow/**, own sibling slices, or make the final Flow verdict.
|
|
495
660
|
Return only the Flow handoff in this exact shape:
|
|
@@ -499,8 +664,10 @@ Return only the Flow handoff in this exact shape:
|
|
|
499
664
|
\`\`\`text
|
|
500
665
|
Overall goal, context only: confirm API error handling is consistent.
|
|
501
666
|
Mode: review
|
|
667
|
+
Pass id and manifest row id: api-error-handling-read / routes-billing
|
|
502
668
|
Your exact slice: the three billing and subscription route modules under src/routes/.
|
|
503
669
|
Expected coverage: 3/3 modules.
|
|
670
|
+
Dependencies and write scope: none; none.
|
|
504
671
|
Do: separate blocking findings from advisory notes and cite file:line evidence.
|
|
505
672
|
Do not: call state-changing Flow tools, edit .flow/**, own sibling slices, or make the final Flow verdict.
|
|
506
673
|
Return only the Flow handoff in this exact shape:
|
|
@@ -510,8 +677,10 @@ Return only the Flow handoff in this exact shape:
|
|
|
510
677
|
\`\`\`text
|
|
511
678
|
Overall goal, context only: confirm API error handling is consistent.
|
|
512
679
|
Mode: audit
|
|
680
|
+
Pass id and manifest row id: api-error-handling-read / routes-admin
|
|
513
681
|
Your exact slice: the five content and admin route modules under src/routes/.
|
|
514
682
|
Expected coverage: 5/5 modules.
|
|
683
|
+
Dependencies and write scope: none; none.
|
|
515
684
|
Do: check each claimed error path against the shared middleware contract and report divergences with evidence.
|
|
516
685
|
Do not: call state-changing Flow tools, edit .flow/**, own sibling slices, or make the final Flow verdict.
|
|
517
686
|
Return only the Flow handoff in this exact shape:
|
|
@@ -522,6 +691,9 @@ Accounting: three manifest rows spawned means three handoffs collected before
|
|
|
522
691
|
synthesis. If slice B returned \`partial\`, the manager would re-spawn it once
|
|
523
692
|
with a narrower scope, then cover it directly, and as a last resort carry it
|
|
524
693
|
into the synthesis explicitly as not-covered.
|
|
694
|
+
The manager fills \`handoffRefs\`, \`verificationStatus\`, \`outcome\`, and
|
|
695
|
+
\`synthesisRef\` for each row before any claim becomes a plan decision or review
|
|
696
|
+
payload.
|
|
525
697
|
|
|
526
698
|
Handoff checks: the manager accepts only reports with terminal status, matching
|
|
527
699
|
coverage counts, concrete file:line evidence, confidence tags, and claims inside
|
|
@@ -539,6 +711,12 @@ Final synthesis: the manager re-reads the relevant route and middleware lines,
|
|
|
539
711
|
keeps only verified or clearly labeled claims, and records one artifact such as
|
|
540
712
|
a plan decision, review payload, or docs patch. Raw handoffs and unverified
|
|
541
713
|
suggestions do not move into the next pass or user-facing answer.
|
|
714
|
+
|
|
715
|
+
If the pass shaped feature execution, the manager records compact accounting in
|
|
716
|
+
\`flow_feature_complete.orchestrationPasses\`, such as pass id
|
|
717
|
+
\`api-error-handling-read\`, kind \`review\`, worker count \`3\`, slice ids
|
|
718
|
+
\`routes-auth\`, \`routes-billing\`, and \`routes-admin\`, verification status
|
|
719
|
+
\`mixed\` or \`passed\`, and a synthesis ref pointing to the manager-owned summary.
|
|
542
720
|
`;
|
|
543
721
|
|
|
544
722
|
// skills/flow/references/recovery-playbook.md
|
|
@@ -822,15 +1000,19 @@ config, or release surfaces in the pass manifest.
|
|
|
822
1000
|
|
|
823
1001
|
Write the pass manifest and the worker prompts exactly as Stages 3 and 4 of
|
|
824
1002
|
\`../../flow/references/parallel-orchestration.md\` define them: one manifest row
|
|
825
|
-
per slice with expected coverage
|
|
826
|
-
prompt per worker naming the mode (usually
|
|
827
|
-
the expected coverage. Discovery-specific
|
|
1003
|
+
per slice with expected coverage, dependencies, write scope, and a verification
|
|
1004
|
+
tier, and a self-contained prompt per worker naming the mode (usually
|
|
1005
|
+
\`evidence\`), the exact slice, and the expected coverage. Discovery-specific
|
|
1006
|
+
rules:
|
|
828
1007
|
|
|
829
1008
|
- Workers are read-only. For validation-oriented discovery, workers may report
|
|
830
1009
|
commands that should be run, and include raw output only for commands they
|
|
831
1010
|
actually ran.
|
|
832
1011
|
- Workers cannot read reference files themselves; paste the matching handoff
|
|
833
1012
|
template from \`../../flow/references/handoff-format.md\` into the prompt.
|
|
1013
|
+
- If discovery finds later features with disjoint path ownership, preserve that
|
|
1014
|
+
fact in feature \`targets\` and \`dependsOn\` so execution can make an explicit
|
|
1015
|
+
serial or candidate-pass decision instead of rediscovering ownership.
|
|
834
1016
|
|
|
835
1017
|
## Synthesis
|
|
836
1018
|
|
|
@@ -1249,6 +1431,11 @@ to execute.
|
|
|
1249
1431
|
validation entry should name the expected test level, such as targeted unit,
|
|
1250
1432
|
integration, browser/e2e, package/build, docs/static, cleanup preservation, or
|
|
1251
1433
|
broad project gate.
|
|
1434
|
+
- When a feature may benefit from parallel implementation, make \`targets\`
|
|
1435
|
+
precise enough for later ownership decisions: name exact modules, docs,
|
|
1436
|
+
commands, or route groups, and use \`dependsOn\` to preserve prerequisite order.
|
|
1437
|
+
Broad shared-contract work should stay in one feature or an earlier foundation
|
|
1438
|
+
feature so later candidate passes can own disjoint paths safely.
|
|
1252
1439
|
- Assign \`reviewDepth\` from risk. Use \`detailed\` for persistence, migration,
|
|
1253
1440
|
concurrency, security, final-delivery-adjacent, or cross-module slices; use
|
|
1254
1441
|
\`standard\` for normal code changes; reserve \`quick\` for low-risk non-behavioral
|
|
@@ -1614,7 +1801,7 @@ Never trim failing output, relabel a failed command as passed, or use "not run"
|
|
|
1614
1801
|
`;
|
|
1615
1802
|
|
|
1616
1803
|
// skills/flow-run/SKILL.md
|
|
1617
|
-
var SKILL_default6 = '---\nname: flow-run\ndescription: "Use when an approved Flow plan has a feature to implement, validate, or complete in the v4 runtime, and the work is scoped to one active feature. For planning a goal first use flow-plan; for the full goal-to-completion loop or resuming a session use flow."\n---\n\n# Flow Run\n\nUse this skill for implementation after a Flow plan is approved. Work one feature at a time.\n\nIf `flow_run_start` is unavailable, stop and tell the user to check that `opencode-plugin-flow` is loaded in OpenCode.\n\n## Start\n\n- Call `flow_status`.\n- If `flow_status` returns a `session.resumePacket` or\n `session.budget.phaseBoundary`, stop the current autonomous loop and report\n the resume instructions. Only call `flow_run_start` with\n `phaseBoundaryAck: true` at the start of a fresh user invocation that is\n explicitly resuming the Flow session; do not acknowledge a boundary inside\n the same uninterrupted loop that created it.\n- Call `flow_run_start` with no `featureId` unless the user or plan requires a specific runnable feature.\n- Treat the returned feature as the sole scope until it is completed, blocked, or reset.\n- Helper rule: when a named helper skill is unavailable, record the gap and\n keep the corresponding claims conservative instead of simulating its checks.\n- Load `flow-deslop` for cleanup/refactor features.\n- Load `flow-ui-quality` for frontend, UX, responsive, accessibility, or visual work.\n\n## Implement\n\n- Read the feature `targets`, `summary`, `validation`, dependencies, and plan `requirements`/`decisions`.\n- Treat the feature\'s `reviewDepth` as the minimum feature-review depth that\n must be recorded in `flow_feature_complete`.\n- Keep edits scoped to the active feature. If new scope appears, stop and replan or defer it to another feature.\n- Preserve unrelated user changes in the worktree.\n- When a wrong assumption invalidates the feature, use `flow_feature_reset`; do not pile patches onto a bad path.\n- Do not stage, commit, push, amend, rebase, publish, or mutate releases as part\n of feature execution. If the user explicitly asks for commit preparation, load\n `flow-commit` only after `flow_feature_complete` has been recorded, unless the\n user explicitly asks for a WIP commit path. Keep Git boundaries separate from\n Flow state recording.\n\n## Validate\n\n- For complex validation, regression-sensitive changes, browser QA, route QA,\n failure-prone checks, unclear coverage, exploratory QA, or\n `validationRun` summarization, load `flow-test` (helper rule applies).\n- Read `references/validation-rubric.md` before completing.\n- Run the strongest practical checks for the changed behavior.\n- Record concrete command names, status, and observed results. "Tests pass" is not evidence.\n- Non-final features complete with `validationScope: "targeted"`.\n- The final feature must run a broad project-level gate and use `validationScope: "broad"`.\n\nFor broad validation research, risky changes, or unclear coverage, use\n`../flow/references/parallel-orchestration.md` to fan out named Flow workers.\nUse the mode-to-agent mapping in that reference instead of generic subagents.\nWrite its pass manifest before fan-out, paste the matching handoff template\nfrom `../flow/references/handoff-format.md` into every worker prompt, and\napply its verification tiers to the handoffs that come back.\nThey may report command output they actually ran or propose focused checks; the\nmanager decides what is strong enough to record.\n\nFor independent implementation attempts, use candidate workers only with\nexplicit user authorization plus isolated worktrees or exact non-overlapping\npath ownership. Treat their output as candidate patches. The manager inspects,\nmerges, validates, and records Flow state serially.\n\n## Review and complete\n\nBefore `flow_feature_complete`, obtain a `featureReview` payload. Load\n`flow-review`; for read-only subagent reviews, the manager receives the review\npacket and records both `featureReviewDepth` and `featureReview`.\n\nSend reviewers a compact review packet. Do not rely on the accumulated parent\nconversation. Include only:\n\n- active feature id, title, summary, `reviewDepth`, targets, validation, and dependencies\n- relevant plan requirements, decisions, and final review policy\n- changed files and a short diff summary\n- validation evidence with exact commands, status, and observed result\n- targeted paths or risk lenses the reviewer must inspect\n\nIf the review returns `status: "failed"`, do not fix inside the review pass.\nRecord the failed attempt by calling `flow_feature_complete` with the otherwise\nprepared completion payload, the failed `featureReview`, and the attempted\n`featureReviewDepth`; the runtime will reject completion and update the retry\nbudget. Default to stopping and reporting the blocker. When the user already\nauthorized autonomous implementation, make at most one repair and run one retry\nreview. If the retry fails or the runtime reports review retry budget\nexhausted, stop with the blocker.\n\nIf `flow_status` reports `setup.skills` or `flow-review` cannot be loaded, do\nnot record a Flow-gated `featureReview` or `finalReview`. You may perform an\nadvisory review using available context or the bundled review fallback provided\nby plugin config, then complete with `status: "needs_input"` if review evidence\nis required to proceed.\n\nFor the final feature, also obtain a `finalReview` payload whose `reviewDepth` equals the approved plan\'s `finalReviewPolicy`.\n\nComplete with:\n\n```json\n{\n "status": "ok",\n "featureId": "active-feature-id",\n "summary": "what changed",\n "artifactsChanged": [{ "path": "src/file.ts" }],\n "validationRun": [\n { "command": "bun test tests/foo.test.ts", "status": "passed", "summary": "3 pass, exercised foo behavior" }\n ],\n "validationScope": "targeted",\n "featureReviewDepth": "standard",\n "featureReview": { "status": "passed", "summary": "review summary", "blockingFindings": [] }\n}\n```\n\nIf `flow_feature_complete` returns a `session.resumePacket` or\n`session.budget.phaseBoundary`, stop after reporting the compact handoff. If\ngenuinely blocked, call `flow_feature_complete` with `status: "needs_input"` and\nan `outcome` that explains the blocker and next step. Never fabricate validation\nor review evidence to force progress.\n';
|
|
1804
|
+
var SKILL_default6 = '---\nname: flow-run\ndescription: "Use when an approved Flow plan has a feature to implement, validate, or complete in the v4 runtime, and the work is scoped to one active feature. For planning a goal first use flow-plan; for the full goal-to-completion loop or resuming a session use flow."\n---\n\n# Flow Run\n\nUse this skill for implementation after a Flow plan is approved. Work one feature at a time.\n\nIf `flow_run_start` is unavailable, stop and tell the user to check that `opencode-plugin-flow` is loaded in OpenCode.\n\n## Start\n\n- Call `flow_status`.\n- If `flow_status` returns a `session.resumePacket` or\n `session.budget.phaseBoundary`, stop the current autonomous loop and report\n the resume instructions. Only call `flow_run_start` with\n `phaseBoundaryAck: true` at the start of a fresh user invocation that is\n explicitly resuming the Flow session; do not acknowledge a boundary inside\n the same uninterrupted loop that created it.\n- Call `flow_run_start` with no `featureId` unless the user or plan requires a specific runnable feature.\n- Treat the returned feature as the sole scope until it is completed, blocked, or reset.\n- Helper rule: when a named helper skill is unavailable, record the gap and\n keep the corresponding claims conservative instead of simulating its checks.\n- Load `flow-deslop` for cleanup/refactor features.\n- Load `flow-ui-quality` for frontend, UX, responsive, accessibility, or visual work.\n\n## Implement\n\n- Read the feature `targets`, `summary`, `validation`, dependencies, and plan `requirements`/`decisions`.\n- Treat the feature\'s `reviewDepth` as the minimum feature-review depth that\n must be recorded in `flow_feature_complete`.\n- For broad, risky, or multi-target work, record an implementation pass\n decision before editing: `serial`, `candidate-exact-path`,\n `candidate-worktree`, `tournament`, or `skipped`. Use\n `../flow/references/parallel-orchestration.md` for the decision rules,\n manifest fields, and compact `orchestrationPasses` record.\n- If candidate workers are skipped, record the reason, such as overlapping\n targets, shared contracts, missing isolation, or no explicit authorization\n for worker edits.\n- Keep edits scoped to the active feature. If new scope appears, stop and replan or defer it to another feature.\n- Preserve unrelated user changes in the worktree.\n- When a wrong assumption invalidates the feature, use `flow_feature_reset`; do not pile patches onto a bad path.\n- Do not stage, commit, push, amend, rebase, publish, or mutate releases as part\n of feature execution. If the user explicitly asks for commit preparation, load\n `flow-commit` only after `flow_feature_complete` has been recorded, unless the\n user explicitly asks for a WIP commit path. Keep Git boundaries separate from\n Flow state recording.\n\n## Validate\n\n- For complex validation, regression-sensitive changes, browser QA, route QA,\n failure-prone checks, unclear coverage, exploratory QA, or\n `validationRun` summarization, load `flow-test` (helper rule applies).\n- Read `references/validation-rubric.md` before completing.\n- Run the strongest practical checks for the changed behavior.\n- Record concrete command names, status, and observed results. "Tests pass" is not evidence.\n- Non-final features complete with `validationScope: "targeted"`.\n- The final feature must run a broad project-level gate and use `validationScope: "broad"`.\n\nFor broad validation research, risky changes, or unclear coverage, use\n`../flow/references/parallel-orchestration.md` to fan out named Flow workers.\nUse the mode-to-agent mapping in that reference instead of generic subagents.\nWrite its pass manifest before fan-out, paste the matching handoff template\nfrom `../flow/references/handoff-format.md` into every worker prompt, and\napply its verification tiers to the handoffs that come back.\nThey may report command output they actually ran or propose focused checks; the\nmanager decides what is strong enough to record.\n\nFor independent implementation attempts, use candidate workers only with\nexplicit user authorization plus isolated worktrees or exact non-overlapping\npath ownership. Treat their output as candidate patches. The manager inspects,\nmerges, validates, and records Flow state serially.\nWhen a candidate pass or serial/skipped implementation decision materially\nshaped the feature, include its compact record in\n`flow_feature_complete.orchestrationPasses`. Do not paste full worker handoffs\nor long logs into the runtime payload.\n\n## Review and complete\n\nBefore `flow_feature_complete`, obtain a `featureReview` payload. Load\n`flow-review`; for read-only subagent reviews, the manager receives the review\npacket and records both `featureReviewDepth` and `featureReview`.\n\nSend reviewers a compact review packet. Do not rely on the accumulated parent\nconversation. Include only:\n\n- active feature id, title, summary, `reviewDepth`, targets, validation, and dependencies\n- relevant plan requirements, decisions, and final review policy\n- changed files and a short diff summary\n- validation evidence with exact commands, status, and observed result\n- targeted paths or risk lenses the reviewer must inspect\n\nIf the review returns `status: "failed"`, do not fix inside the review pass.\nRecord the failed attempt by calling `flow_feature_complete` with the otherwise\nprepared completion payload, the failed `featureReview`, and the attempted\n`featureReviewDepth`; the runtime will reject completion and update the retry\nbudget. Default to stopping and reporting the blocker. When the user already\nauthorized autonomous implementation, make at most one repair and run one retry\nreview. If the retry fails or the runtime reports review retry budget\nexhausted, stop with the blocker.\n\nIf `flow_status` reports `setup.skills` or `flow-review` cannot be loaded, do\nnot record a Flow-gated `featureReview` or `finalReview`. You may perform an\nadvisory review using available context or the bundled review fallback provided\nby plugin config, then complete with `status: "needs_input"` if review evidence\nis required to proceed.\n\nFor the final feature, also obtain a `finalReview` payload whose `reviewDepth` equals the approved plan\'s `finalReviewPolicy`.\n\nComplete with:\n\n```json\n{\n "status": "ok",\n "featureId": "active-feature-id",\n "summary": "what changed",\n "artifactsChanged": [{ "path": "src/file.ts" }],\n "validationRun": [\n { "command": "bun test tests/foo.test.ts", "status": "passed", "summary": "3 pass, exercised foo behavior" }\n ],\n "validationScope": "targeted",\n "featureReviewDepth": "standard",\n "featureReview": { "status": "passed", "summary": "review summary", "blockingFindings": [] },\n "orchestrationPasses": [\n {\n "id": "active-feature-id-implementation-decision",\n "kind": "implementation-decision",\n "decision": "serial",\n "decisionReason": "Shared contract edits made worker ownership unsafe.",\n "writeScope": "manager-serial",\n "verificationStatus": "not-needed",\n "outcome": "accepted"\n }\n ]\n}\n```\n\nIf `flow_feature_complete` returns a `session.resumePacket` or\n`session.budget.phaseBoundary`, stop after reporting the compact handoff. If\ngenuinely blocked, call `flow_feature_complete` with `status: "needs_input"` and\nan `outcome` that explains the blocker and next step. Never fabricate validation\nor review evidence to force progress.\n';
|
|
1618
1805
|
|
|
1619
1806
|
// skills/flow-test/SKILL.md
|
|
1620
1807
|
var SKILL_default7 = `---
|
|
@@ -2635,6 +2822,78 @@ var FeatureReviewDepthSchema = z.enum([
|
|
|
2635
2822
|
"detailed"
|
|
2636
2823
|
]);
|
|
2637
2824
|
var FinalReviewPolicySchema = z.enum(["broad", "detailed"]);
|
|
2825
|
+
var OrchestrationPassKindSchema = z.enum([
|
|
2826
|
+
"discovery",
|
|
2827
|
+
"audit",
|
|
2828
|
+
"review",
|
|
2829
|
+
"validation",
|
|
2830
|
+
"verification",
|
|
2831
|
+
"candidate",
|
|
2832
|
+
"implementation-decision"
|
|
2833
|
+
]);
|
|
2834
|
+
var OrchestrationModeSchema = z.enum([
|
|
2835
|
+
"evidence",
|
|
2836
|
+
"review",
|
|
2837
|
+
"validation",
|
|
2838
|
+
"audit",
|
|
2839
|
+
"verifier",
|
|
2840
|
+
"candidate-implementation"
|
|
2841
|
+
]);
|
|
2842
|
+
var OrchestrationDecisionSchema = z.enum([
|
|
2843
|
+
"serial",
|
|
2844
|
+
"parallel",
|
|
2845
|
+
"candidate-exact-path",
|
|
2846
|
+
"candidate-worktree",
|
|
2847
|
+
"tournament",
|
|
2848
|
+
"skipped"
|
|
2849
|
+
]);
|
|
2850
|
+
var OrchestrationWriteScopeSchema = z.enum([
|
|
2851
|
+
"none",
|
|
2852
|
+
"manager-serial",
|
|
2853
|
+
"exact-path",
|
|
2854
|
+
"isolated-worktree",
|
|
2855
|
+
"mixed"
|
|
2856
|
+
]);
|
|
2857
|
+
var OrchestrationVerificationStatusSchema = z.enum([
|
|
2858
|
+
"not-needed",
|
|
2859
|
+
"pending",
|
|
2860
|
+
"passed",
|
|
2861
|
+
"failed",
|
|
2862
|
+
"mixed",
|
|
2863
|
+
"downgraded"
|
|
2864
|
+
]);
|
|
2865
|
+
var OrchestrationOutcomeSchema = z.enum([
|
|
2866
|
+
"accepted",
|
|
2867
|
+
"rejected",
|
|
2868
|
+
"partial",
|
|
2869
|
+
"not-covered",
|
|
2870
|
+
"superseded"
|
|
2871
|
+
]);
|
|
2872
|
+
var OrchestrationPassRecordSchema = z.object({
|
|
2873
|
+
id: z.string().min(1),
|
|
2874
|
+
kind: OrchestrationPassKindSchema,
|
|
2875
|
+
decision: OrchestrationDecisionSchema.optional(),
|
|
2876
|
+
decisionReason: z.string().min(1).optional(),
|
|
2877
|
+
modes: z.array(OrchestrationModeSchema).default([]),
|
|
2878
|
+
workerCount: z.number().int().nonnegative().default(0),
|
|
2879
|
+
candidateWorkerCount: z.number().int().nonnegative().default(0),
|
|
2880
|
+
verifierWorkerCount: z.number().int().nonnegative().default(0),
|
|
2881
|
+
sliceIds: z.array(z.string().min(1)).default([]),
|
|
2882
|
+
dependsOn: z.array(z.string().min(1)).default([]),
|
|
2883
|
+
writeScope: OrchestrationWriteScopeSchema.default("none"),
|
|
2884
|
+
handoffRefs: z.array(z.string().min(1)).default([]),
|
|
2885
|
+
verificationStatus: OrchestrationVerificationStatusSchema.default("not-needed"),
|
|
2886
|
+
outcome: OrchestrationOutcomeSchema.default("accepted"),
|
|
2887
|
+
synthesisRef: z.string().min(1).optional()
|
|
2888
|
+
}).strict();
|
|
2889
|
+
var OrchestrationTelemetrySchema = z.object({
|
|
2890
|
+
passCount: z.number().int().nonnegative().default(0),
|
|
2891
|
+
workerCount: z.number().int().nonnegative().default(0),
|
|
2892
|
+
candidatePassCount: z.number().int().nonnegative().default(0),
|
|
2893
|
+
verifierPassCount: z.number().int().nonnegative().default(0),
|
|
2894
|
+
skippedCandidateDecisionCount: z.number().int().nonnegative().default(0),
|
|
2895
|
+
latestPasses: z.array(OrchestrationPassRecordSchema).default([])
|
|
2896
|
+
}).strict();
|
|
2638
2897
|
var ReviewFindingSchema = z.object({
|
|
2639
2898
|
summary: z.string().min(1),
|
|
2640
2899
|
severity: z.enum(["blocking", "advisory"]).default("blocking")
|
|
@@ -2704,7 +2963,8 @@ var WorkerResultSchema = z.discriminatedUnion("status", [
|
|
|
2704
2963
|
featureReviewDepth: FeatureReviewDepthSchema,
|
|
2705
2964
|
featureReview: ReviewSchema,
|
|
2706
2965
|
finalReview: FinalReviewSchema.optional(),
|
|
2707
|
-
outcome: WorkerOutcomeSchema.optional()
|
|
2966
|
+
outcome: WorkerOutcomeSchema.optional(),
|
|
2967
|
+
orchestrationPasses: z.array(OrchestrationPassRecordSchema).default([])
|
|
2708
2968
|
}).strict(),
|
|
2709
2969
|
z.object({
|
|
2710
2970
|
status: z.literal("needs_input"),
|
|
@@ -2716,7 +2976,8 @@ var WorkerResultSchema = z.discriminatedUnion("status", [
|
|
|
2716
2976
|
featureReviewDepth: FeatureReviewDepthSchema.optional(),
|
|
2717
2977
|
featureReview: ReviewSchema.optional(),
|
|
2718
2978
|
finalReview: FinalReviewSchema.optional(),
|
|
2719
|
-
outcome: NeedsInputOutcomeSchema
|
|
2979
|
+
outcome: NeedsInputOutcomeSchema,
|
|
2980
|
+
orchestrationPasses: z.array(OrchestrationPassRecordSchema).default([])
|
|
2720
2981
|
}).strict()
|
|
2721
2982
|
]).superRefine((value, ctx) => {
|
|
2722
2983
|
if (value.status === "ok" && value.outcome?.kind && value.outcome.kind !== "completed") {
|
|
@@ -2738,7 +2999,8 @@ var ExecutionHistoryEntrySchema = z.object({
|
|
|
2738
2999
|
featureReviewDepth: FeatureReviewDepthSchema.optional(),
|
|
2739
3000
|
featureReview: ReviewSchema.optional(),
|
|
2740
3001
|
finalReview: FinalReviewSchema.optional(),
|
|
2741
|
-
outcome: WorkerOutcomeSchema.optional()
|
|
3002
|
+
outcome: WorkerOutcomeSchema.optional(),
|
|
3003
|
+
orchestrationPasses: z.array(OrchestrationPassRecordSchema).default([])
|
|
2742
3004
|
}).strict();
|
|
2743
3005
|
var TokenTelemetrySchema = z.object({
|
|
2744
3006
|
source: z.enum(["host_unavailable", "reported"]).default("host_unavailable"),
|
|
@@ -2764,6 +3026,14 @@ var BudgetTelemetrySchema = z.object({
|
|
|
2764
3026
|
cacheReadTokens: null,
|
|
2765
3027
|
nonCacheTokens: null
|
|
2766
3028
|
}),
|
|
3029
|
+
orchestration: OrchestrationTelemetrySchema.default({
|
|
3030
|
+
passCount: 0,
|
|
3031
|
+
workerCount: 0,
|
|
3032
|
+
candidatePassCount: 0,
|
|
3033
|
+
verifierPassCount: 0,
|
|
3034
|
+
skippedCandidateDecisionCount: 0,
|
|
3035
|
+
latestPasses: []
|
|
3036
|
+
}),
|
|
2767
3037
|
phaseBoundary: PhaseBoundarySchema.nullable().default(null)
|
|
2768
3038
|
}).strict();
|
|
2769
3039
|
var SessionSchema = z.object({
|
|
@@ -2787,6 +3057,14 @@ var SessionSchema = z.object({
|
|
|
2787
3057
|
cacheReadTokens: null,
|
|
2788
3058
|
nonCacheTokens: null
|
|
2789
3059
|
},
|
|
3060
|
+
orchestration: {
|
|
3061
|
+
passCount: 0,
|
|
3062
|
+
workerCount: 0,
|
|
3063
|
+
candidatePassCount: 0,
|
|
3064
|
+
verifierPassCount: 0,
|
|
3065
|
+
skippedCandidateDecisionCount: 0,
|
|
3066
|
+
latestPasses: []
|
|
3067
|
+
},
|
|
2790
3068
|
phaseBoundary: null
|
|
2791
3069
|
}),
|
|
2792
3070
|
closure: z.object({
|
|
@@ -3227,6 +3505,7 @@ function nowIso() {
|
|
|
3227
3505
|
// src/runtime/transitions.ts
|
|
3228
3506
|
var MAX_HISTORY_ENTRIES = 500;
|
|
3229
3507
|
var MAX_FAILED_REVIEW_ATTEMPTS_PER_FEATURE = 2;
|
|
3508
|
+
var MAX_LATEST_ORCHESTRATION_PASSES = 50;
|
|
3230
3509
|
var FEATURE_REVIEW_DEPTH_RANK = {
|
|
3231
3510
|
quick: 0,
|
|
3232
3511
|
standard: 1,
|
|
@@ -3248,7 +3527,8 @@ function historyEntryFor(worker, status) {
|
|
|
3248
3527
|
featureReviewDepth: worker.featureReviewDepth,
|
|
3249
3528
|
featureReview: worker.featureReview,
|
|
3250
3529
|
finalReview: worker.finalReview,
|
|
3251
|
-
outcome: worker.outcome
|
|
3530
|
+
outcome: worker.outcome,
|
|
3531
|
+
orchestrationPasses: worker.orchestrationPasses
|
|
3252
3532
|
};
|
|
3253
3533
|
}
|
|
3254
3534
|
function initialBudgetTelemetry() {
|
|
@@ -3264,6 +3544,14 @@ function initialBudgetTelemetry() {
|
|
|
3264
3544
|
cacheReadTokens: null,
|
|
3265
3545
|
nonCacheTokens: null
|
|
3266
3546
|
},
|
|
3547
|
+
orchestration: {
|
|
3548
|
+
passCount: 0,
|
|
3549
|
+
workerCount: 0,
|
|
3550
|
+
candidatePassCount: 0,
|
|
3551
|
+
verifierPassCount: 0,
|
|
3552
|
+
skippedCandidateDecisionCount: 0,
|
|
3553
|
+
latestPasses: []
|
|
3554
|
+
},
|
|
3267
3555
|
phaseBoundary: null
|
|
3268
3556
|
};
|
|
3269
3557
|
}
|
|
@@ -3278,9 +3566,50 @@ function normalizeBudgetTelemetry(session) {
|
|
|
3278
3566
|
tokenTelemetry: {
|
|
3279
3567
|
...defaults.tokenTelemetry,
|
|
3280
3568
|
...session.budget.tokenTelemetry
|
|
3569
|
+
},
|
|
3570
|
+
orchestration: {
|
|
3571
|
+
...defaults.orchestration,
|
|
3572
|
+
...session.budget.orchestration,
|
|
3573
|
+
latestPasses: [...session.budget.orchestration?.latestPasses ?? []]
|
|
3281
3574
|
}
|
|
3282
3575
|
};
|
|
3283
3576
|
}
|
|
3577
|
+
function passUsesCandidate(pass) {
|
|
3578
|
+
return pass.kind === "candidate" || pass.modes.includes("candidate-implementation") || pass.decision === "candidate-exact-path" || pass.decision === "candidate-worktree" || pass.decision === "tournament";
|
|
3579
|
+
}
|
|
3580
|
+
function passUsesVerifier(pass) {
|
|
3581
|
+
return pass.kind === "verification" || pass.modes.includes("verifier");
|
|
3582
|
+
}
|
|
3583
|
+
function recordOrchestrationPasses(budget, passes) {
|
|
3584
|
+
if (passes.length === 0)
|
|
3585
|
+
return budget;
|
|
3586
|
+
const seenPassIds = new Set(budget.orchestration.latestPasses.map((pass) => pass.id));
|
|
3587
|
+
const newPasses = [];
|
|
3588
|
+
for (const pass of passes) {
|
|
3589
|
+
if (seenPassIds.has(pass.id))
|
|
3590
|
+
continue;
|
|
3591
|
+
seenPassIds.add(pass.id);
|
|
3592
|
+
newPasses.push(pass);
|
|
3593
|
+
}
|
|
3594
|
+
if (newPasses.length === 0)
|
|
3595
|
+
return budget;
|
|
3596
|
+
const latestPasses = [...budget.orchestration.latestPasses, ...newPasses];
|
|
3597
|
+
return {
|
|
3598
|
+
...budget,
|
|
3599
|
+
orchestration: {
|
|
3600
|
+
passCount: budget.orchestration.passCount + newPasses.length,
|
|
3601
|
+
workerCount: budget.orchestration.workerCount + newPasses.reduce((total, pass) => total + pass.workerCount, 0),
|
|
3602
|
+
candidatePassCount: budget.orchestration.candidatePassCount + newPasses.filter(passUsesCandidate).length,
|
|
3603
|
+
verifierPassCount: budget.orchestration.verifierPassCount + newPasses.filter(passUsesVerifier).length,
|
|
3604
|
+
skippedCandidateDecisionCount: budget.orchestration.skippedCandidateDecisionCount + newPasses.filter((pass) => pass.kind === "implementation-decision" && pass.decision === "skipped").length,
|
|
3605
|
+
latestPasses: latestPasses.length > MAX_LATEST_ORCHESTRATION_PASSES ? latestPasses.slice(latestPasses.length - MAX_LATEST_ORCHESTRATION_PASSES) : latestPasses
|
|
3606
|
+
}
|
|
3607
|
+
};
|
|
3608
|
+
}
|
|
3609
|
+
function sessionWithOrchestrationPasses(session, passes) {
|
|
3610
|
+
const budget = recordOrchestrationPasses(normalizeBudgetTelemetry(session), passes);
|
|
3611
|
+
return budget === session.budget ? session : { ...session, budget };
|
|
3612
|
+
}
|
|
3284
3613
|
function ok(value) {
|
|
3285
3614
|
return { ok: true, value };
|
|
3286
3615
|
}
|
|
@@ -3640,48 +3969,49 @@ function completeFeature(session, input) {
|
|
|
3640
3969
|
if (worker.featureId !== session.activeFeatureId) {
|
|
3641
3970
|
return fail(`Worker result feature '${worker.featureId}' does not match active feature '${session.activeFeatureId}'.`);
|
|
3642
3971
|
}
|
|
3972
|
+
const sessionWithPasses = sessionWithOrchestrationPasses(session, worker.orchestrationPasses);
|
|
3643
3973
|
if (worker.status === "needs_input") {
|
|
3644
3974
|
const entry2 = historyEntryFor(worker, "needs_input");
|
|
3645
|
-
const budget2 = normalizeBudgetTelemetry(
|
|
3975
|
+
const budget2 = normalizeBudgetTelemetry(sessionWithPasses);
|
|
3646
3976
|
return ok(touch({
|
|
3647
|
-
...
|
|
3977
|
+
...sessionWithPasses,
|
|
3648
3978
|
status: "blocked",
|
|
3649
3979
|
activeFeatureId: null,
|
|
3650
3980
|
plan: {
|
|
3651
3981
|
...session.plan,
|
|
3652
3982
|
features: updateFeature(session.plan.features, worker.featureId, "blocked")
|
|
3653
3983
|
},
|
|
3654
|
-
history: appendHistory(
|
|
3984
|
+
history: appendHistory(sessionWithPasses.history, entry2),
|
|
3655
3985
|
budget: budget2,
|
|
3656
3986
|
lastError: null
|
|
3657
3987
|
}));
|
|
3658
3988
|
}
|
|
3659
3989
|
if (!isPassingReview(worker.featureReview)) {
|
|
3660
|
-
return failedReviewCompletion(
|
|
3990
|
+
return failedReviewCompletion(sessionWithPasses, worker, worker.featureReview, "feature");
|
|
3661
3991
|
}
|
|
3662
|
-
if (finalFeature(
|
|
3663
|
-
return failedReviewCompletion(
|
|
3992
|
+
if (finalFeature(sessionWithPasses, worker.featureId) && worker.finalReview && !isPassingReview(worker.finalReview)) {
|
|
3993
|
+
return failedReviewCompletion(sessionWithPasses, worker, worker.finalReview, "final");
|
|
3664
3994
|
}
|
|
3665
|
-
const validation = validateCompletion(
|
|
3995
|
+
const validation = validateCompletion(sessionWithPasses, worker);
|
|
3666
3996
|
if (!validation.ok)
|
|
3667
3997
|
return validation;
|
|
3668
3998
|
const entry = historyEntryFor(worker, "completed");
|
|
3669
3999
|
const features = updateFeature(session.plan.features, worker.featureId, "completed");
|
|
3670
4000
|
const allComplete = features.every((feature) => feature.status === "completed");
|
|
3671
4001
|
const now = nowIso();
|
|
3672
|
-
const budget = completionBudget(
|
|
4002
|
+
const budget = completionBudget(sessionWithPasses, worker);
|
|
3673
4003
|
return ok(touch({
|
|
3674
|
-
...
|
|
4004
|
+
...sessionWithPasses,
|
|
3675
4005
|
status: allComplete ? "completed" : "ready",
|
|
3676
4006
|
activeFeatureId: null,
|
|
3677
4007
|
plan: { ...session.plan, features },
|
|
3678
|
-
history: appendHistory(
|
|
4008
|
+
history: appendHistory(sessionWithPasses.history, entry),
|
|
3679
4009
|
budget,
|
|
3680
4010
|
closure: allComplete ? { kind: "completed", summary: worker.summary, recordedAt: now } : null,
|
|
3681
4011
|
lastError: null,
|
|
3682
4012
|
timestamps: {
|
|
3683
|
-
...
|
|
3684
|
-
completedAt: allComplete ? now :
|
|
4013
|
+
...sessionWithPasses.timestamps,
|
|
4014
|
+
completedAt: allComplete ? now : sessionWithPasses.timestamps.completedAt
|
|
3685
4015
|
}
|
|
3686
4016
|
}));
|
|
3687
4017
|
}
|
|
@@ -3808,6 +4138,7 @@ function summarizeSession(session) {
|
|
|
3808
4138
|
reviewCount: budget.reviewCount,
|
|
3809
4139
|
failedReviewCount: budget.failedReviewCount,
|
|
3810
4140
|
failedReviewAttemptsByFeature: budget.failedReviewAttemptsByFeature,
|
|
4141
|
+
orchestration: budget.orchestration,
|
|
3811
4142
|
tokenTelemetry: {
|
|
3812
4143
|
...budget.tokenTelemetry,
|
|
3813
4144
|
note: budget.tokenTelemetry.source === "host_unavailable" ? "OpenCode does not expose per-turn usage to this plugin surface; Flow can enforce review checkpoints, but token thresholds remain manager-observed." : undefined
|
|
@@ -3882,7 +4213,8 @@ var FlowFeatureCompleteToolSchema = z2.object({
|
|
|
3882
4213
|
featureReviewDepth: FeatureReviewDepthSchema.optional(),
|
|
3883
4214
|
featureReview: ReviewSchema.optional(),
|
|
3884
4215
|
finalReview: FinalReviewSchema.optional(),
|
|
3885
|
-
outcome: z2.union([WorkerOutcomeSchema, NeedsInputOutcomeSchema]).optional()
|
|
4216
|
+
outcome: z2.union([WorkerOutcomeSchema, NeedsInputOutcomeSchema]).optional(),
|
|
4217
|
+
orchestrationPasses: z2.array(OrchestrationPassRecordSchema).optional()
|
|
3886
4218
|
}).strict();
|
|
3887
4219
|
function missingSessionResponse() {
|
|
3888
4220
|
return {
|
|
@@ -4249,4 +4581,4 @@ export {
|
|
|
4249
4581
|
plugin_default as default
|
|
4250
4582
|
};
|
|
4251
4583
|
|
|
4252
|
-
//# debugId=
|
|
4584
|
+
//# debugId=283DE939C516DF8064756E2164756E21
|