opencode-plugin-flow 4.1.16 → 4.1.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/dist/cli.js CHANGED
@@ -1,11 +1,14 @@
1
1
  #!/usr/bin/env node
2
- import{createHash as Pe}from"node:crypto";import{mkdir as je,readdir as re,readFile as Se,rm as We,writeFile as b}from"node:fs/promises";import{createRequire as Oe}from"node:module";import{dirname as Be,join as u,normalize as ze,sep as Ee}from"node:path";var S=`# Flow worker handoff contract
2
+ import{createHash as ze}from"node:crypto";import{mkdir as Ee,readdir as ne,readFile as Be,rm as ie,writeFile as x}from"node:fs/promises";import{createRequire as Ve}from"node:module";import{dirname as Ne,join as h,normalize as Ge,sep as Me}from"node:path";var j=`# Flow worker handoff contract
3
3
 
4
4
  Flow managers merge only the worker's final response. Treat that response as the
5
5
  worker report of record: it must include the assigned scope, what was actually
6
6
  covered, the evidence for each useful claim, and the remaining gaps. End worker
7
7
  prompts with "Return only this Flow handoff."
8
8
 
9
+ Sections: evidence/review/validation/audit worker report, verifier worker report,
10
+ and candidate implementation worker report.
11
+
9
12
  Status meanings:
10
13
 
11
14
  - \`success\`: the assigned scope was covered, or any skipped items are explicitly
@@ -137,86 +140,24 @@ live-verified | test-verified | type-check-only | not-verified
137
140
 
138
141
  The manager must inspect and validate any candidate patch before recording Flow
139
142
  completion.
140
- `;var W=`# Parallel full-wave example
141
-
142
- Use this example after \`parallel-orchestration.md\` when a broad Flow task needs a
143
- concrete worker wave shape.
144
-
145
- Goal: review whether bundled Flow command guidance is self-contained and aligned
146
- with hidden worker permissions.
147
-
148
- Serial orientation: the manager reads \`src/config-shared.ts\` enough to identify
149
- five public command templates and six hidden worker configs. The manager keeps
150
- \`flow-status\` local because it is one line and does not need a worker.
151
-
152
- Coverage gate: ten countable items remain after the local check.
153
-
154
- - Slice A: \`flow-auto\`, \`flow-plan\`, and \`flow-run\` templates, expected 3/10.
155
- - Slice B: \`flow-review\` template plus \`flow-reviewer\` config, expected 2/10.
156
- - Slice C: remaining hidden worker permission blocks, expected 5/10 after
157
- excluding the reviewer already covered by Slice B.
158
-
159
- Worker prompts:
160
-
161
- \`\`\`text
162
- Overall goal, context only: confirm Flow public commands are self-contained.
163
- Mode: evidence
164
- Your exact slice: flow-auto, flow-plan, and flow-run templates in src/config-shared.ts.
165
- Expected coverage: 3/3 templates.
166
- Do: report bundled sections, setup preflight coverage, and any gaps with file:line evidence.
167
- Do not: call state-changing Flow tools, edit .flow/**, own sibling slices, or make the final Flow verdict.
168
- Return exactly the matching handoff shape from handoff-format.md.
169
- \`\`\`
170
-
171
- \`\`\`text
172
- Overall goal, context only: confirm Flow review command and hidden reviewer behavior.
173
- Mode: review
174
- Your exact slice: flow-review command template and flow-reviewer config in src/config-shared.ts.
175
- Expected coverage: 2/2 surfaces.
176
- Do: separate blocking findings from advisory notes and cite file:line evidence.
177
- Do not: call state-changing Flow tools, edit .flow/**, own sibling slices, or make the final Flow verdict.
178
- Return exactly the matching handoff shape from handoff-format.md.
179
- \`\`\`
180
-
181
- \`\`\`text
182
- Overall goal, context only: confirm hidden worker permissions match the orchestration model.
183
- Mode: audit
184
- Your exact slice: flow-evidence-worker, flow-validation-worker, flow-audit-worker, flow-candidate-worker, and flow-verifier-worker permissions in src/config-shared.ts.
185
- Expected coverage: 5/5 worker permission blocks.
186
- Do: report edit, bash, task, skill, flow_*, and flow_status permissions with evidence.
187
- Do not: call state-changing Flow tools, edit .flow/**, own sibling slices, or make the final Flow verdict.
188
- Return exactly the matching handoff shape from handoff-format.md.
189
- \`\`\`
190
-
191
- Handoff checks: the manager accepts only reports with terminal status, matching
192
- coverage counts, concrete file:line evidence, confidence tags, and claims inside
193
- the assigned slice. A claim such as \`[high] validation workers may run commands;
194
- evidence: src/config-shared.ts:281-288; corroboration: single source\` is usable.
195
- A claim such as \`[high] permissions look safe; evidence: config reviewed\` is
196
- dropped or retasked.
197
-
198
- Verifier pass: the manager sends any single-source claim that will enter the
199
- Flow payload to \`flow-verifier-worker\`, for example: \`C1: validation, audit,
200
- candidate, and verifier workers have bash ask while evidence and review workers
201
- have bash deny; sources: src/config-shared.ts worker permission blocks\`.
202
-
203
- Final synthesis: the manager re-reads the relevant config lines, keeps only
204
- verified or clearly labeled claims, and records one artifact such as a plan
205
- decision, review payload, or docs patch. Raw handoffs and unverified suggestions
206
- do not move into the next wave or user-facing answer.
207
- `;var O=`# Parallel orchestration
143
+ `;var W=`# Parallel orchestration
208
144
 
209
145
  Use fan-out when Flow work is broad enough that independent workers can gather
210
146
  evidence faster than one linear pass. The manager still owns the Flow session:
211
147
  only the manager calls state-changing Flow tools, approves plans, completes
212
148
  features, records reviews, or closes sessions.
213
149
 
214
- Read these companion references before a broad wave:
150
+ Sections: quick path, operational defaults, manager sequence, modes, permission
151
+ contract, worker rules, prompt contract, handoff location, and follow-up passes.
215
152
 
153
+ Read these companion references before a broad parallel pass:
154
+
155
+ - \`parallel-pass-patterns.md\` for pass selection, effort defaults, and stop or
156
+ follow-up rules.
216
157
  - \`handoff-format.md\` for the exact worker response shapes.
217
158
  - \`verification-gates.md\` for coverage checks, handoff acceptance, verifier
218
159
  triggers, and synthesis rules.
219
- - \`parallel-full-wave-example.md\` for a concrete end-to-end wave after the rules
160
+ - \`parallel-pass-example.md\` for a concrete end-to-end pass after the rules
220
161
  below are clear.
221
162
 
222
163
  ## Quick path
@@ -237,9 +178,9 @@ Read these companion references before a broad wave:
237
178
 
238
179
  - Prefer serial work when the scope is small, tightly coupled, or blocked by one
239
180
  decision that must be made before slices are meaningful.
240
- - A normal first wave is two to five workers with independent slices. Use more
181
+ - A normal first pass is two to five workers with independent slices. Use more
241
182
  only when the coverage gate is countable and the slices remain non-overlapping.
242
- - Run at most one routine follow-up wave. Extra waves need an explicit manager
183
+ - Run at most one routine follow-up pass. Extra passes need an explicit manager
243
184
  reason, such as a high-stakes verifier check or a newly discovered bounded
244
185
  slice.
245
186
  - Do not fan out just to keep agents busy. Every worker should reduce a known
@@ -274,7 +215,7 @@ Skip fan-out when:
274
215
  scope, and carry confidence labels.
275
216
  8. Send important low-confidence, single-source, contested, or citation-heavy
276
217
  claims to \`flow-verifier-worker\`.
277
- 9. Run second waves only for material gaps, conflicts, narrowed scope, or
218
+ 9. Run follow-up passes only for material gaps, conflicts, narrowed scope, or
278
219
  verification needs.
279
220
  10. Apply the manager synthesis barrier: keep only distilled, evidence-backed
280
221
  claims and synthesize one Flow artifact, such as plan fields, completion
@@ -363,7 +304,7 @@ Your exact slice: <paths, modules, command, claim ids, risk lens, or worktree>
363
304
  Expected coverage: <count, paths, range, or complete question set>
364
305
  Do: <bounded actions>
365
306
  Do not: call state-changing Flow tools, edit .flow/**, own sibling slices, or make the final Flow verdict.
366
- Return exactly the matching handoff shape from handoff-format.md.
307
+ Return only the matching Flow handoff from handoff-format.md.
367
308
  \`\`\`
368
309
 
369
310
  For research or current-doc slices, require source checks for versioned or
@@ -390,11 +331,11 @@ the smallest check that can settle the disagreement.
390
331
 
391
332
  The manager synthesis barrier means raw handoffs do not move forward by default.
392
333
  Only claims that survived coverage, evidence, confidence, and verifier checks may
393
- enter the next wave, Flow payload, patch decision, or user-facing answer.
334
+ enter the next pass, Flow payload, patch decision, or user-facing answer.
394
335
 
395
- ## Second waves
336
+ ## Follow-up passes
396
337
 
397
- Start a follow-up wave when first-wave handoffs reveal:
338
+ Start a follow-up pass when first-pass handoffs reveal:
398
339
 
399
340
  - missing coverage in the original slice map.
400
341
  - conflicting findings that matter to the Flow decision.
@@ -403,14 +344,176 @@ Start a follow-up wave when first-wave handoffs reveal:
403
344
  - bounded implementation candidates after research converges.
404
345
 
405
346
  Do not recurse by default. If a worker says it needs another worker, the manager
406
- decides whether that is a second wave and writes the next bounded prompt.
407
- `;var B='# Recovery playbook\n\nUse this when a Flow tool returns `status: "error"`, a blocker, or a `nextAction` that conflicts with memory.\n\n## First response\n\n1. Re-anchor with `flow_status`.\n2. Read the returned `summary`, `recovery`, `lastError`, and active feature.\n3. Fix the cause, then retry the smallest valid Flow action.\n\n## Common cases\n\n- `missing_session`: start with `flow_plan_save` using the user\'s goal.\n- `missing_goal`: ask for a concrete goal before planning.\n- `Approved plans cannot be changed`: use `flow_feature_reset` when only affected features need another pass; otherwise close and start a new goal.\n- `No feature is currently running`: call `flow_run_start` before completing.\n- `already in progress`: finish, reset, or block the active feature before starting another.\n- `Completion requires recorded validation evidence`: run real validation and include at least one passing `validationRun`.\n- `Completion requires all recorded validation to pass`: fix failures and rerun. Do not relabel failed checks as passed.\n- `Non-final feature completion requires targeted validation`: use `validationScope: "targeted"` for ordinary features.\n- `Final feature completion requires broad validation`: run the project-level gate and use `validationScope: "broad"`.\n- `Completion requires a passing featureReview`: run or request a real review and include a passing `featureReview` only when there are no blocking findings.\n- `Final feature completion requires a finalReview`: perform final review and include `finalReview`.\n- `Final review depth must match the plan policy`: use `reviewDepth` equal to the approved plan\'s `finalReviewPolicy`; valid final-review values are `broad` and `detailed`.\n- `Cannot close ... unfinished features`: complete, reset, defer, or abandon honestly. Do not mark completed while work remains.\n\n## Reset guidance\n\nUse `flow_feature_reset` when the active or completed work was built on the wrong assumption, validation revealed a design issue, dependencies need to be rerun, or dependent features must be invalidated. Resetting a feature also resets its dependents.\n\n## Closure guidance\n\nUse `flow_session_close`:\n\n- `completed`: only after all planned features are complete.\n- `deferred`: the user intentionally postpones unfinished work.\n- `abandoned`: the session should be archived without claiming delivery.\n\nAfter closure, the active `.flow/session.json` is removed and the archived JSON is stored under `.flow/history/`.\n';var z=`# Verification gates
347
+ decides whether that is a follow-up pass and writes the next bounded prompt.
348
+ `;var O=`# Parallel pass example
349
+
350
+ Use this example after \`parallel-orchestration.md\` when a broad Flow task needs a
351
+ concrete pass shape.
352
+
353
+ Goal: review whether bundled Flow command guidance is self-contained and aligned
354
+ with hidden worker permissions.
355
+
356
+ Serial orientation: the manager reads \`src/config-shared.ts\` enough to identify
357
+ five public command templates and six hidden worker configs. The manager keeps
358
+ \`flow-status\` local because it is one line and does not need a worker.
359
+
360
+ Coverage gate: ten countable items remain after the local check.
361
+
362
+ - Slice A: \`flow-auto\`, \`flow-plan\`, and \`flow-run\` templates, expected 3/10.
363
+ - Slice B: \`flow-review\` template plus \`flow-reviewer\` config, expected 2/10.
364
+ - Slice C: remaining hidden worker permission blocks, expected 5/10 after
365
+ excluding the reviewer already covered by Slice B.
366
+
367
+ Worker prompts:
368
+
369
+ \`\`\`text
370
+ Overall goal, context only: confirm Flow public commands are self-contained.
371
+ Mode: evidence
372
+ Your exact slice: flow-auto, flow-plan, and flow-run templates in src/config-shared.ts.
373
+ Expected coverage: 3/3 templates.
374
+ Do: report bundled sections, setup preflight coverage, and any gaps with file:line evidence.
375
+ Do not: call state-changing Flow tools, edit .flow/**, own sibling slices, or make the final Flow verdict.
376
+ Return only the matching Flow handoff from handoff-format.md.
377
+ \`\`\`
378
+
379
+ \`\`\`text
380
+ Overall goal, context only: confirm Flow review command and hidden reviewer behavior.
381
+ Mode: review
382
+ Your exact slice: flow-review command template and flow-reviewer config in src/config-shared.ts.
383
+ Expected coverage: 2/2 surfaces.
384
+ Do: separate blocking findings from advisory notes and cite file:line evidence.
385
+ Do not: call state-changing Flow tools, edit .flow/**, own sibling slices, or make the final Flow verdict.
386
+ Return only the matching Flow handoff from handoff-format.md.
387
+ \`\`\`
388
+
389
+ \`\`\`text
390
+ Overall goal, context only: confirm hidden worker permissions match the orchestration model.
391
+ Mode: audit
392
+ Your exact slice: flow-evidence-worker, flow-validation-worker, flow-audit-worker, flow-candidate-worker, and flow-verifier-worker permissions in src/config-shared.ts.
393
+ Expected coverage: 5/5 worker permission blocks.
394
+ Do: report edit, bash, task, skill, flow_*, and flow_status permissions with evidence.
395
+ Do not: call state-changing Flow tools, edit .flow/**, own sibling slices, or make the final Flow verdict.
396
+ Return only the matching Flow handoff from handoff-format.md.
397
+ \`\`\`
398
+
399
+ Handoff checks: the manager accepts only reports with terminal status, matching
400
+ coverage counts, concrete file:line evidence, confidence tags, and claims inside
401
+ the assigned slice. A claim such as \`[high] validation workers may run commands;
402
+ evidence: src/config-shared.ts:307-320; corroboration: single source\` is usable.
403
+ A claim such as \`[high] permissions look safe; evidence: config reviewed\` is
404
+ dropped or retasked.
405
+
406
+ Verifier pass: the manager sends any single-source claim that will enter the
407
+ Flow payload to \`flow-verifier-worker\`, for example: \`C1: validation, audit,
408
+ candidate, and verifier workers have bash ask while evidence and review workers
409
+ have bash deny; sources: src/config-shared.ts worker permission blocks\`.
410
+
411
+ Final synthesis: the manager re-reads the relevant config lines, keeps only
412
+ verified or clearly labeled claims, and records one artifact such as a plan
413
+ decision, review payload, or docs patch. Raw handoffs and unverified suggestions
414
+ do not move into the next pass or user-facing answer.
415
+ `;var z=`# Parallel pass patterns
416
+
417
+ Flow uses parallel workers to reduce uncertainty, not to delegate decisions.
418
+ Each pass has a bounded purpose, an explicit coverage rule, and one
419
+ manager-owned synthesis result.
420
+
421
+ ## Choose a pass
422
+
423
+ | Situation | Flow pass | Output the manager may synthesize |
424
+ | --- | --- | --- |
425
+ | Repo shape is unclear before planning | Discovery pass | Requirements, decisions, targets, validation entries, or a review-first feature |
426
+ | A broad finding set needs refutation | Audit pass | Surviving findings with guards checked and gaps named |
427
+ | Changed files or risk lenses are too broad for one review pass | Review pass | One \`featureReview\` or \`finalReview\` payload owned by the manager |
428
+ | Test strategy or route coverage is unclear | Validation pass | Candidate commands or authorized raw command evidence |
429
+ | A claim is single-source, surprising, high-stakes, or payload-bound | Verification pass | Per-claim keep, narrow, rewrite, or remove decisions |
430
+ | Multiple implementation paths are plausible | Candidate pass | Candidate patches inspected and validated by the manager before use |
431
+
432
+ Prefer serial work when one file, command, or design question determines the
433
+ next step. A parallel pass should reduce a named planning, validation, review,
434
+ audit, or implementation uncertainty.
435
+
436
+ ## Pass Shapes
437
+
438
+ ### Discovery pass
439
+
440
+ Use before planning when the manager has oriented enough to name disjoint slices
441
+ but not enough to write reliable plan fields. Workers read specific modules,
442
+ routes, docs, commands, or risk lenses. The manager turns only evidenced claims
443
+ into plan fields.
444
+
445
+ ### Audit pass
446
+
447
+ Use when a report starts from candidate findings. Workers actively look for
448
+ guards, lifecycle resets, deployment constraints, and counterexamples before
449
+ reporting a finding. A finding that lacks refutation work stays advisory or
450
+ becomes a follow-up question.
451
+
452
+ ### Review pass
453
+
454
+ Use when changed files or risks can be reviewed independently. Review workers
455
+ separate blocking findings from advisory notes. The manager resolves conflicts,
456
+ checks cited artifacts, and returns one review payload.
457
+
458
+ ### Validation pass
459
+
460
+ Use when coverage is unclear or command evidence can be gathered independently.
461
+ Validation workers may run only manager-authorized commands and must report
462
+ exact command, status, raw outcome summary, coverage, confidence, and gaps.
463
+
464
+ ### Verification pass
465
+
466
+ Use for atomic claims. Give the verifier claim ids, cited sources or commands,
467
+ and the acceptance question. Do not ask a verifier to redesign the work or
468
+ review the whole feature.
469
+
470
+ ### Candidate pass
471
+
472
+ Use only with explicit user authorization plus isolated worktrees or exact
473
+ non-overlapping path ownership. Candidate patches are proposals until the
474
+ manager inspects, merges or rejects them, and validates the main workspace.
475
+
476
+ ## Effort Defaults
477
+
478
+ - Start with two to five workers. Use more only when the coverage gate is
479
+ countable and the manager can verify every handoff.
480
+ - Run at most one routine follow-up pass. Extra passes need a stated reason,
481
+ such as a high-stakes verification check or a newly discovered bounded slice.
482
+ - Spend effort where being wrong costs more: public API, persistence, security,
483
+ permissions, release behavior, data loss, and Flow payload claims.
484
+ - Do not fan out to keep agents busy. Worker setup and synthesis have real cost.
485
+
486
+ ## Stop And Extend
487
+
488
+ Stop after a pass when:
489
+
490
+ - the coverage rule is satisfied.
491
+ - accepted claims are evidenced, scoped, and confidence-labeled.
492
+ - material single-source, contested, high-stakes, or payload-bound claims have
493
+ been verified or downgraded.
494
+ - remaining gaps are explicit and do not block the Flow artifact being produced.
495
+
496
+ Start a bounded follow-up pass only when:
497
+
498
+ - the original slice map missed material scope.
499
+ - workers disagree on a claim that affects the Flow decision.
500
+ - a high-stakes or payload-bound claim needs verification.
501
+ - a first pass exposes a narrower implementation or validation slice worth
502
+ isolating.
503
+
504
+ The manager synthesis barrier applies after every pass: raw handoffs remain
505
+ candidate evidence until the manager checks coverage, resolves conflicts,
506
+ preserves confidence, and records one Flow-owned artifact.
507
+ `;var E='# Recovery playbook\n\nUse this when a Flow tool returns `status: "error"`, a blocker, or a `nextAction` that conflicts with memory.\n\n## First response\n\n1. Re-anchor with `flow_status`.\n2. Read the returned `summary`, `recovery`, `lastError`, and active feature.\n3. Fix the cause, then retry the smallest valid Flow action.\n\n## Common cases\n\n- `missing_session`: start with `flow_plan_save` using the user\'s goal.\n- `missing_goal`: ask for a concrete goal before planning.\n- `Approved plans cannot be changed`: use `flow_feature_reset` when only affected features need another pass; otherwise close and start a new goal.\n- `No feature is currently running`: call `flow_run_start` before completing.\n- `already in progress`: finish, reset, or block the active feature before starting another.\n- `Completion requires recorded validation evidence`: run real validation and include at least one passing `validationRun`.\n- `Completion requires all recorded validation to pass`: fix failures and rerun. Do not relabel failed checks as passed.\n- `Non-final feature completion requires targeted validation`: use `validationScope: "targeted"` for ordinary features.\n- `Final feature completion requires broad validation`: run the project-level gate and use `validationScope: "broad"`.\n- `Completion requires a passing featureReview`: run or request a real review and include a passing `featureReview` only when there are no blocking findings.\n- `Final feature completion requires a finalReview`: perform final review and include `finalReview`.\n- `Final review depth must match the plan policy`: use `reviewDepth` equal to the approved plan\'s `finalReviewPolicy`; valid final-review values are `broad` and `detailed`.\n- `Cannot close ... unfinished features`: complete, reset, defer, or abandon honestly. Do not mark completed while work remains.\n\n## Reset guidance\n\nUse `flow_feature_reset` when the active or completed work was built on the wrong assumption, validation revealed a design issue, dependencies need to be rerun, or dependent features must be invalidated. Resetting a feature also resets its dependents.\n\n## Closure guidance\n\nUse `flow_session_close`:\n\n- `completed`: only after all planned features are complete.\n- `deferred`: the user intentionally postpones unfinished work.\n- `abandoned`: the session should be archived without claiming delivery.\n\nAfter closure, the active `.flow/session.json` is removed and the archived JSON is stored under `.flow/history/`.\n';var B=`# Verification gates
408
508
 
409
509
  Verification is how Flow keeps parallel work from turning into parallel
410
510
  guesswork. Worker handoffs are candidate evidence; the manager decides what can
411
511
  enter the plan, validation record, review payload, audit report, or final
412
512
  answer.
413
513
 
514
+ Sections: before fan-out, every handoff, verifier triggers, verification tiers,
515
+ Flow payload acceptance, and manager synthesis barrier.
516
+
414
517
  ## Before fan-out
415
518
 
416
519
  Run a pre-fan-out gate after serial orientation and before spawning workers:
@@ -458,6 +561,25 @@ Use \`flow-verifier-worker\` when a claim is:
458
561
  Give the verifier atomic claims, cited sources or commands, and the acceptance
459
562
  question. Do not ask it to redesign the work or review the whole feature.
460
563
 
564
+ ## Verification tiers
565
+
566
+ Use the cheapest check that matches the risk:
567
+
568
+ - **Accept locally**: low-risk claims with direct evidence that the manager can
569
+ cheaply inspect or recount.
570
+ - **Verify once**: single-source, surprising, inferred, citation-heavy, or
571
+ Flow-payload-bound claims.
572
+ - **Verify strongly**: claims that affect security, persistence, permissions,
573
+ public API behavior, release behavior, data loss, or blocking review outcome.
574
+ Use independent verifier checks, manager-run commands, or direct artifact
575
+ inspection strong enough to settle the claim.
576
+ - **Do not accept**: claims without concrete evidence, claims outside the
577
+ assigned slice, claims contradicted by inspected artifacts, or claims where the
578
+ cited evidence supports only the topic rather than the assertion.
579
+
580
+ Verifier prompts should use stable claim ids, one atomic assertion per id, the
581
+ cited source or command for each id, and the exact acceptance question.
582
+
461
583
  ## Flow payload acceptance
462
584
 
463
585
  Planning fields may use worker evidence only when the source and scope are clear.
@@ -496,7 +618,7 @@ Before presenting or recording the result:
496
618
 
497
619
  \`Status: success\` only says the worker believes its slice is done. The manager
498
620
  still checks coverage and evidence before trusting the result.
499
- `;var E=`---
621
+ `;var V=`---
500
622
  name: flow
501
623
  description: Run the end-to-end Flow loop for skills-first OpenCode work. Use when a user asks for Flow-guided planning through implementation, resumable autonomous delivery, session status, or completion with validation and review gates.
502
624
  ---
@@ -518,7 +640,7 @@ Use Flow as a minimal state ledger, not as a framework. Skills provide judgment;
518
640
  5. On the final feature, run broad validation and include \`finalReview\` in the same \`flow_feature_complete\` call. Its \`reviewDepth\` must match the plan's \`finalReviewPolicy\`.
519
641
  6. After all features are complete, archive the session with \`flow_session_close\` using \`kind: "completed"\`.
520
642
 
521
- Use \`references/parallel-orchestration.md\` for broad read-only discovery, audit, validation, review, verification, or candidate implementation waves. Hidden Flow workers are injected by plugin config; invoke the named worker when it is available. Its \`references/handoff-format.md\` and \`references/verification-gates.md\` companions define the worker contracts. The manager owns every \`flow_*\` state change.
643
+ Use \`references/parallel-orchestration.md\` for broad read-only discovery, audit, validation, review, verification, or candidate implementation passes. Hidden Flow workers are injected by plugin config; invoke the named worker when it is available. Its \`references/parallel-pass-patterns.md\`, \`references/handoff-format.md\`, and \`references/verification-gates.md\` companions define pass selection, worker contracts, and claim acceptance. The manager owns every \`flow_*\` state change.
522
644
 
523
645
  Do not commit, push, amend, rebase, publish, or mutate releases during the
524
646
  autonomous Flow loop. Load \`flow-commit\` only when the user explicitly asks for
@@ -729,7 +851,7 @@ Weak evidence includes:
729
851
  - Public contracts and compatibility shims remain intact or were explicitly planned.
730
852
  - Deleted code is actually unreachable or obsolete.
731
853
  - Validation can catch a realistic mistake in the refactor.
732
- `;var V=`# Deslop smell rubric
854
+ `;var M=`# Deslop smell rubric
733
855
 
734
856
  Use this rubric to turn vague cleanup instincts into reviewable findings.
735
857
 
@@ -763,7 +885,7 @@ class; severity; location; evidence read; refutation checked; why it matters; sa
763
885
  \`\`\`
764
886
 
765
887
  Rate as blocking only when the smell materially raises defect risk, blocks planned work, hides behavior, or makes the success claim unverifiable. Style-only cleanup is advisory.
766
- `;var M=`---
888
+ `;var L=`---
767
889
  name: flow-deslop
768
890
  description: Clean up and refactor code with evidence-backed code-smell analysis. Use for AI-slop removal, overengineering reduction, maintainability refactors, behavior-preserving cleanup, duplicated or bloated code, speculative abstractions, dead code, or broad cleanup/refactor review.
769
891
  ---
@@ -805,11 +927,11 @@ For each claimed smell removal, verify:
805
927
  - **blast radius** — public contracts and downstream callers still work.
806
928
 
807
929
  Never approve cleanup because it "looks cleaner" without evidence. Tests passing is necessary but not sufficient when the refactor changes structure across files.
808
- `;var L=`# Parallel discovery
930
+ `;var $=`# Parallel discovery
809
931
 
810
932
  Use this only after a serial orientation pass has identified the repo shape and the likely slices. Workers are read-only evidence gatherers; the planner owns the plan.
811
933
 
812
- For broad waves, also load \`../../flow/references/parallel-orchestration.md\`.
934
+ For broad parallel passes, also load \`../../flow/references/parallel-orchestration.md\`.
813
935
  Use its pre-fan-out coverage gate and
814
936
  \`../../flow/references/handoff-format.md\` response shapes.
815
937
 
@@ -823,7 +945,7 @@ Use its pre-fan-out coverage gate and
823
945
 
824
946
  ## Flow repo default slices
825
947
 
826
- For this repository, good first-wave slices are:
948
+ For this repository, good first-pass slices are:
827
949
 
828
950
  - Runtime gates: \`src/runtime/schema.ts\`, \`src/runtime/transitions.ts\`,
829
951
  \`src/runtime/api.ts\`, and \`tests/runtime-gates.test.ts\`.
@@ -881,7 +1003,7 @@ If workers disagree, inspect the source artifact yourself. If a candidate findin
881
1003
  Apply the manager synthesis barrier from
882
1004
  \`../../flow/references/verification-gates.md\`: only distilled, evidence-backed
883
1005
  claims become plan fields.
884
- `;var $=`# Planning examples
1006
+ `;var Q=`# Planning examples
885
1007
 
886
1008
  ## Rate limiting feature set
887
1009
 
@@ -966,7 +1088,7 @@ Better plan:
966
1088
  - Validation that only says "manual testing".
967
1089
  - Targets that name the entire repo.
968
1090
  - Features with hidden dependencies instead of \`dependsOn\`.
969
- `;var Q=`---
1091
+ `;var K=`---
970
1092
  name: flow-plan
971
1093
  description: "Plan Flow work for the v4 skills-first runtime: inspect the repo, decompose a user goal into right-sized features, save a draft with flow_plan_save, and approve it with flow_plan_approve."
972
1094
  ---
@@ -1036,7 +1158,7 @@ Use only \`finalReviewPolicy: "broad"\` or \`"detailed"\`. These are the canonic
1036
1158
  After saving, summarize the plan to the user. Call \`flow_plan_approve\` only after explicit user approval, unless the user already authorized autonomous implementation. Approved plans are immutable; changing them later requires reset/closure rather than silent edits.
1037
1159
 
1038
1160
  See \`references/planning-examples.md\` for payload examples and decomposition anti-patterns.
1039
- `;var K=`# Review rubric
1161
+ `;var Y=`# Review rubric
1040
1162
 
1041
1163
  Use this to decide whether a \`featureReview\` or \`finalReview\` payload may pass.
1042
1164
 
@@ -1124,7 +1246,7 @@ When reviewing a findings report, verify findings adversarially:
1124
1246
  - Downgrade or reject findings that do not survive refutation.
1125
1247
 
1126
1248
  Approve only on evidence actually inspected. A review is a claim of coverage, not a courtesy stamp.
1127
- `;var Y=`---
1249
+ `;var X=`---
1128
1250
  name: flow-review
1129
1251
  description: "Review Flow work in the v4 runtime: inspect feature or final-session changes, classify findings, and return featureReview or finalReview payloads for flow_feature_complete."
1130
1252
  ---
@@ -1194,7 +1316,7 @@ Use \`status: "failed"\` when any blocking finding remains. Advisory findings ma
1194
1316
  \`finalReview\` payload.
1195
1317
 
1196
1318
  Never approve to unblock completion, fix findings in the review pass, or vouch for validation you did not inspect.
1197
- `;var X=`# Audit findings rubric
1319
+ `;var J=`# Audit findings rubric
1198
1320
 
1199
1321
  What counts as a valid finding when the feature's deliverable is a findings report: a codebase audit, a review-first feature, or any report whose findings a later feature will fix. The commands you run are still governed by \`validation-rubric.md\`; this rubric governs the findings themselves.
1200
1322
 
@@ -1247,7 +1369,7 @@ follow-up order — correctness and persisted/user-input surfaces first
1247
1369
  \`\`\`
1248
1370
 
1249
1371
  Never: promote a hypothesis to blocking severity; cite a line you did not read in context; rate severity against a deployment model the product does not have; pad the report to look thorough — six verified findings outrank nine where three die on first contact.
1250
- `;var J=`# Validation evidence rubric
1372
+ `;var Z=`# Validation evidence rubric
1251
1373
 
1252
1374
  Use this before recording \`flow_feature_complete\`.
1253
1375
 
@@ -1304,7 +1426,7 @@ Broad validation usually means the repo's full check command, full relevant test
1304
1426
  - If validation needs external access, missing credentials, or ambiguous user input, record \`status: "needs_input"\` with an honest \`outcome\`.
1305
1427
 
1306
1428
  Never trim failing output, relabel a failed command as passed, or use "not run" as completion evidence.
1307
- `;var Z=`---
1429
+ `;var H=`---
1308
1430
  name: flow-run
1309
1431
  description: "Execute one approved Flow feature in the v4 runtime: start a feature with flow_run_start, make scoped changes, gather real validation evidence, obtain review payloads, and complete with flow_feature_complete."
1310
1432
  ---
@@ -1391,7 +1513,7 @@ Complete with:
1391
1513
  \`\`\`
1392
1514
 
1393
1515
  If genuinely blocked, call \`flow_feature_complete\` with \`status: "needs_input"\` and an \`outcome\` that explains the blocker and next step. Never fabricate validation or review evidence to force progress.
1394
- `;var H=`---
1516
+ `;var ee=`---
1395
1517
  name: flow-test
1396
1518
  description: Test, validate, make test plans, triage failures, and gather Flow validation evidence. Use when selecting checks, running tests, running browser QA for UI changes, classifying failures, or preparing validationRun evidence for flow_feature_complete.
1397
1519
  ---
@@ -1515,7 +1637,7 @@ covered. Static inspection alone is a gap for behavioral changes.
1515
1637
 
1516
1638
  Never relabel a failed command as passed, invent output, or use "not run" as
1517
1639
  completion evidence.
1518
- `;var ee=`# UI quality rubric
1640
+ `;var ae=`# UI quality rubric
1519
1641
 
1520
1642
  Use this rubric for frontend planning, implementation, and review.
1521
1643
 
@@ -1559,7 +1681,7 @@ class; severity; location or screenshot area; evidence inspected; user impact; f
1559
1681
  \`\`\`
1560
1682
 
1561
1683
  Blocking UI findings are issues that prevent task completion, hide required information, break accessibility basics, create incoherent layout at supported sizes, or make the visual success claim unverifiable.
1562
- `;var ae=`# Visual verification workflow
1684
+ `;var te=`# Visual verification workflow
1563
1685
 
1564
1686
  Use this workflow when UI changes can be run locally. Flow execution may create visual evidence; Flow review usually assesses recorded evidence because the reviewer is read-only.
1565
1687
 
@@ -1599,7 +1721,7 @@ Record the reason and use the strongest available substitute:
1599
1721
  - code inspection against existing component patterns.
1600
1722
 
1601
1723
  Do not claim visual polish was verified if no visual artifact was inspected.
1602
- `;var te=`---
1724
+ `;var oe=`---
1603
1725
  name: flow-ui-quality
1604
1726
  description: Review and improve frontend UI quality for Flow work. Use for UX/UI design, frontend polish, visual quality review, responsive and accessible interfaces, interaction states, screenshots, browser-verified UI work, and avoiding generic AI-generated UI.
1605
1727
  ---
@@ -1647,23 +1769,23 @@ Approve only when the interface is both useful and inspectable:
1647
1769
  - Screenshot/browser evidence supports the claim whenever feasible.
1648
1770
 
1649
1771
  Never approve a UI change based only on code shape. If users will judge it visually, Flow evidence should include visual inspection.
1650
- `;var y=[{name:"flow",files:[{relativePath:"SKILL.md",content:E},{relativePath:"references/recovery-playbook.md",content:B},{relativePath:"references/parallel-orchestration.md",content:O},{relativePath:"references/parallel-full-wave-example.md",content:W},{relativePath:"references/handoff-format.md",content:S},{relativePath:"references/verification-gates.md",content:z}]},{name:"flow-plan",files:[{relativePath:"SKILL.md",content:Q},{relativePath:"references/planning-examples.md",content:$},{relativePath:"references/parallel-discovery.md",content:L}]},{name:"flow-run",files:[{relativePath:"SKILL.md",content:Z},{relativePath:"references/validation-rubric.md",content:J},{relativePath:"references/audit-rubric.md",content:X}]},{name:"flow-test",files:[{relativePath:"SKILL.md",content:H}]},{name:"flow-review",files:[{relativePath:"SKILL.md",content:Y},{relativePath:"references/review-rubric.md",content:K}]},{name:"flow-deslop",files:[{relativePath:"SKILL.md",content:M},{relativePath:"references/smell-rubric.md",content:V},{relativePath:"references/refactor-workflow.md",content:G}]},{name:"flow-ui-quality",files:[{relativePath:"SKILL.md",content:te},{relativePath:"references/ui-rubric.md",content:ee},{relativePath:"references/visual-verification.md",content:ae}]},{name:"flow-commit",files:[{relativePath:"SKILL.md",content:N}]}];var q=".flow-skill-version";function _(){return process.env.HOME??process.env.USERPROFILE??""}function D(e=_()){return u(e,".config","opencode","skills")}function g(e){return Pe("sha256").update(e).digest("hex")}function k(e,a){return[`version=${a}`,...e.files.map((t)=>`file=${t.relativePath} sha256=${g(t.content)}`),""].join(`
1651
- `)}async function m(e){try{return await Se(e,"utf8")}catch(a){if(a.code==="ENOENT")return null;throw a}}function T(e){let a=new Map;if(!e)return a;for(let t of e.split(/\r?\n/)){let r=/^file=(.+) sha256=([a-f0-9]{64})$/.exec(t)??/^file=(.+)=sha256:([a-f0-9]{64})$/.exec(t);if(r?.[1]&&r[2])a.set(r[1],r[2]);let s=/^hash=sha256:([a-f0-9]{64})$/.exec(t);if(s?.[1]&&!a.has("SKILL.md"))a.set("SKILL.md",s[1])}return a}function Ne(e){if(!e)return null;for(let a of e.split(/\r?\n/)){let t=/^version=(.+)$/.exec(a);if(t?.[1])return t[1]}return null}function x(e,a){let t=ze(u(e,...a.split("/")));if(t!==e&&t.startsWith(`${e}${Ee}`))return t;throw Error(`Unsafe skill file path '${a}'.`)}async function Ge(e,a){let t=`${e}.backup.${g(a).slice(0,12)}`;for(let r=0;;r+=1){let s=r===0?t:`${t}.${r}`;try{return await b(s,a,{encoding:"utf8",flag:"wx"}),s}catch(n){if(n.code==="EEXIST")continue;throw n}}}async function Ve(e,a,t){let r=u(t,e.name),s=u(r,q),n=await m(s),d=T(n);if(await m(u(r,"SKILL.md"))!==null&&n===null)return{name:e.name,action:"skipped_foreign"};let i=!1,l=[];for(let o of e.files){let c=x(r,o.relativePath),h=await m(c);if(h===o.content)continue;i=!0;let w=d.get(o.relativePath);if(h!==null&&(w?g(h)!==w:n!==null))l.push(await Ge(c,h))}if(!i&&n===k(e,a))return{name:e.name,action:"unchanged"};if(!i)return await b(s,k(e,a),"utf8"),{name:e.name,action:"marker_updated"};let v=n!==null;for(let o of e.files){let c=x(r,o.relativePath);await je(Be(c),{recursive:!0}),await b(c,o.content,"utf8")}return await b(s,k(e,a),"utf8"),{name:e.name,action:l.length>0?"updated_with_backup":v?"updated":"installed",...l.length>0?{backupPaths:l}:{}}}function Me(){return y.map((e)=>e.name)}function Le(e){return`npx -y opencode-plugin-flow@${e} doctor`}function F(){if(process.env.npm_package_version)return process.env.npm_package_version;try{let e=Oe(import.meta.url);for(let a of["../package.json","../../package.json"])try{let t=e(a);if(t.version)return t.version}catch{}}catch{}return"0.0.0"}async function ne(e,a=_()){let t=D(a);return Promise.all(y.map((r)=>Ve(r,e,t)))}async function se(e=F(),a=_()){let t=D(a),r=new Set(Me()),s=await Promise.all(y.map(async(o)=>{let c=u(t,o.name),h=await m(u(c,q)),w=Ne(h),P=T(h);if(await m(u(c,"SKILL.md"))===null)return{name:o.name,path:c,status:"missing",markerVersion:w,missingFiles:o.files.map((f)=>f.relativePath),editedFiles:[],outdatedFiles:[]};if(h===null)return{name:o.name,path:c,status:"foreign",markerVersion:w,missingFiles:[],editedFiles:[],outdatedFiles:[]};let R=[],U=[],C=[];for(let f of o.files){let A=await m(x(c,f.relativePath));if(A===null){R.push(f.relativePath);continue}if(A===f.content)continue;let j=P.get(f.relativePath);if(j&&g(A)!==j){U.push(f.relativePath);continue}C.push(f.relativePath)}let de=h!==k(o,e),le=R.length>0?"incomplete":U.length>0?"edited":de||C.length>0?"outdated":"ok";return{name:o.name,path:c,status:le,markerVersion:w,missingFiles:R,editedFiles:U,outdatedFiles:C}})),n=[];try{n=await re(t)}catch(o){if(o.code!=="ENOENT")throw o}let d=n.filter((o)=>(o==="flow"||o.startsWith("flow-"))&&!r.has(o)).map((o)=>u(t,o)),p=s.filter((o)=>["missing","incomplete","outdated"].includes(o.status)).map((o)=>o.name),i=s.filter((o)=>["foreign","edited"].includes(o.status)).map((o)=>o.name),l=i.length>0,v=p.length>0;return{status:l?"action_required":v?"sync_required":"ok",version:e,root:t,expectedSkills:[...r],skills:s,syncRequiredSkills:p,actionRequiredSkills:i,unmanagedFlowSkills:d}}function oe(e,a,t){if(t.length===0)return;e.push(`- ${a}: ${t.join(", ")}`)}function ie(e){let a=["Flow doctor",`- status: ${e.status}`,`- plugin version: ${e.version}`,`- skills root: ${e.root}`,`- expected skills: ${e.expectedSkills.join(", ")}`];oe(a,"startup sync can install/update",e.syncRequiredSkills),oe(a,"needs user decision",e.actionRequiredSkills),a.push("","Skills:");for(let t of e.skills){if(a.push(`- ${t.name}: ${t.status} (${t.path})${t.markerVersion?` marker=${t.markerVersion}`:""}`),t.missingFiles.length>0)a.push(` missing: ${t.missingFiles.join(", ")}`);if(t.editedFiles.length>0)a.push(` edited: ${t.editedFiles.join(", ")}`);if(t.outdatedFiles.length>0)a.push(` outdated: ${t.outdatedFiles.join(", ")}`)}if(e.unmanagedFlowSkills.length>0){a.push("","Unmanaged Flow-like skill folders:");for(let t of e.unmanagedFlowSkills)a.push(`- ${t}`)}if(a.push("","Recommendation:"),e.status==="ok")a.push("- Flow skills are present and current.");else if(e.status==="sync_required")a.push("- Start or restart OpenCode with opencode-plugin-flow enabled so startup sync can install or update the listed skills. If Flow then reports restart_required, restart OpenCode once more so the refreshed skill registry is used.");else a.push("- Resolve user-owned or edited managed skill folders, then restart OpenCode. Move a folder aside to let Flow recreate it, or keep it intentionally as a local override.");return a.push(`- Details command: ${Le(e.version)}`),`${a.join(`
1772
+ `;var k=[{name:"flow",files:[{relativePath:"SKILL.md",content:V},{relativePath:"references/recovery-playbook.md",content:E},{relativePath:"references/parallel-orchestration.md",content:W},{relativePath:"references/parallel-pass-patterns.md",content:z},{relativePath:"references/parallel-pass-example.md",content:O},{relativePath:"references/handoff-format.md",content:j},{relativePath:"references/verification-gates.md",content:B}]},{name:"flow-plan",files:[{relativePath:"SKILL.md",content:K},{relativePath:"references/planning-examples.md",content:Q},{relativePath:"references/parallel-discovery.md",content:$}]},{name:"flow-run",files:[{relativePath:"SKILL.md",content:H},{relativePath:"references/validation-rubric.md",content:Z},{relativePath:"references/audit-rubric.md",content:J}]},{name:"flow-test",files:[{relativePath:"SKILL.md",content:ee}]},{name:"flow-review",files:[{relativePath:"SKILL.md",content:X},{relativePath:"references/review-rubric.md",content:Y}]},{name:"flow-deslop",files:[{relativePath:"SKILL.md",content:L},{relativePath:"references/smell-rubric.md",content:M},{relativePath:"references/refactor-workflow.md",content:G}]},{name:"flow-ui-quality",files:[{relativePath:"SKILL.md",content:oe},{relativePath:"references/ui-rubric.md",content:ae},{relativePath:"references/visual-verification.md",content:te}]},{name:"flow-commit",files:[{relativePath:"SKILL.md",content:N}]}];var D=".flow-skill-version";function _(){return process.env.HOME??process.env.USERPROFILE??""}function T(e=_()){return h(e,".config","opencode","skills")}function v(e){return ze("sha256").update(e).digest("hex")}function F(e,a){return[`version=${a}`,...e.files.map((t)=>`file=${t.relativePath} sha256=${v(t.content)}`),""].join(`
1773
+ `)}async function f(e){try{return await Be(e,"utf8")}catch(a){if(a.code==="ENOENT")return null;throw a}}function P(e){let a=new Map;if(!e)return a;for(let t of e.split(/\r?\n/)){let r=/^file=(.+) sha256=([a-f0-9]{64})$/.exec(t)??/^file=(.+)=sha256:([a-f0-9]{64})$/.exec(t);if(r?.[1]&&r[2])a.set(r[1],r[2]);let n=/^hash=sha256:([a-f0-9]{64})$/.exec(t);if(n?.[1]&&!a.has("SKILL.md"))a.set("SKILL.md",n[1])}return a}function Le(e){if(!e)return null;for(let a of e.split(/\r?\n/)){let t=/^version=(.+)$/.exec(a);if(t?.[1])return t[1]}return null}function b(e,a){let t=Ge(h(e,...a.split("/")));if(t!==e&&t.startsWith(`${e}${Me}`))return t;throw Error(`Unsafe skill file path '${a}'.`)}async function re(e,a){let t=`${e}.backup.${v(a).slice(0,12)}`;for(let r=0;;r+=1){let n=r===0?t:`${t}.${r}`;try{return await x(n,a,{encoding:"utf8",flag:"wx"}),n}catch(s){if(s.code==="EEXIST")continue;throw s}}}async function $e(e,a,t){let r=h(t,e.name),n=h(r,D),s=await f(n),d=P(s);if(await f(h(r,"SKILL.md"))!==null&&s===null)return{name:e.name,action:"skipped_foreign"};let c=!1,l=[],y=new Set(e.files.map((i)=>i.relativePath));for(let i of e.files){let u=b(r,i.relativePath),p=await f(u);if(p===i.content)continue;c=!0;let w=d.get(i.relativePath);if(p!==null&&(w?v(p)!==w:s!==null))l.push(await re(u,p))}for(let[i,u]of d){if(y.has(i))continue;let p=b(r,i),w=await f(p);if(w===null)continue;if(c=!0,v(w)!==u)l.push(await re(p,w));await ie(p,{force:!0})}if(!c&&s===F(e,a))return{name:e.name,action:"unchanged"};if(!c)return await x(n,F(e,a),"utf8"),{name:e.name,action:"marker_updated"};let o=s!==null;for(let i of e.files){let u=b(r,i.relativePath);await Ee(Ne(u),{recursive:!0}),await x(u,i.content,"utf8")}return await x(n,F(e,a),"utf8"),{name:e.name,action:l.length>0?"updated_with_backup":o?"updated":"installed",...l.length>0?{backupPaths:l}:{}}}function Qe(){return k.map((e)=>e.name)}function Ke(e){return`npx -y opencode-plugin-flow@${e} doctor`}function I(){if(process.env.npm_package_version)return process.env.npm_package_version;try{let e=Ve(import.meta.url);for(let a of["../package.json","../../package.json"])try{let t=e(a);if(t.version)return t.version}catch{}}catch{}return"0.0.0"}async function ce(e,a=_()){let t=T(a);return Promise.all(k.map((r)=>$e(r,e,t)))}async function de(e=I(),a=_()){let t=T(a),r=new Set(Qe()),n=await Promise.all(k.map(async(o)=>{let i=h(t,o.name),u=await f(h(i,D)),p=Le(u),w=P(u);if(await f(h(i,"SKILL.md"))===null)return{name:o.name,path:i,status:"missing",markerVersion:p,missingFiles:o.files.map((g)=>g.relativePath),editedFiles:[],outdatedFiles:[]};if(u===null)return{name:o.name,path:i,status:"foreign",markerVersion:p,missingFiles:[],editedFiles:[],outdatedFiles:[]};let U=[],A=[],C=[];for(let g of o.files){let q=await f(b(i,g.relativePath));if(q===null){U.push(g.relativePath);continue}if(q===g.content)continue;let S=w.get(g.relativePath);if(S&&v(q)!==S){A.push(g.relativePath);continue}C.push(g.relativePath)}let he=u!==F(o,e),fe=U.length>0?"incomplete":A.length>0?"edited":he||C.length>0?"outdated":"ok";return{name:o.name,path:i,status:fe,markerVersion:p,missingFiles:U,editedFiles:A,outdatedFiles:C}})),s=[];try{s=await ne(t)}catch(o){if(o.code!=="ENOENT")throw o}let d=s.filter((o)=>(o==="flow"||o.startsWith("flow-"))&&!r.has(o)).map((o)=>h(t,o)),m=n.filter((o)=>["missing","incomplete","outdated"].includes(o.status)).map((o)=>o.name),c=n.filter((o)=>["foreign","edited"].includes(o.status)).map((o)=>o.name),l=c.length>0,y=m.length>0;return{status:l?"action_required":y?"sync_required":"ok",version:e,root:t,expectedSkills:[...r],skills:n,syncRequiredSkills:m,actionRequiredSkills:c,unmanagedFlowSkills:d}}function se(e,a,t){if(t.length===0)return;e.push(`- ${a}: ${t.join(", ")}`)}function le(e){let a=["Flow doctor",`- status: ${e.status}`,`- plugin version: ${e.version}`,`- skills root: ${e.root}`,`- expected skills: ${e.expectedSkills.join(", ")}`];se(a,"startup sync can install/update",e.syncRequiredSkills),se(a,"needs user decision",e.actionRequiredSkills),a.push("","Skills:");for(let t of e.skills){if(a.push(`- ${t.name}: ${t.status} (${t.path})${t.markerVersion?` marker=${t.markerVersion}`:""}`),t.missingFiles.length>0)a.push(` missing: ${t.missingFiles.join(", ")}`);if(t.editedFiles.length>0)a.push(` edited: ${t.editedFiles.join(", ")}`);if(t.outdatedFiles.length>0)a.push(` outdated: ${t.outdatedFiles.join(", ")}`)}if(e.unmanagedFlowSkills.length>0){a.push("","Unmanaged Flow-like skill folders:");for(let t of e.unmanagedFlowSkills)a.push(`- ${t}`)}if(a.push("","Recommendation:"),e.status==="ok")a.push("- Flow skills are present and current.");else if(e.status==="sync_required")a.push("- Start or restart OpenCode with opencode-plugin-flow enabled so startup sync can install or update the listed skills. If Flow then reports restart_required, restart OpenCode once more so the refreshed skill registry is used.");else a.push("- Resolve user-owned or edited managed skill folders, then restart OpenCode. Move a folder aside to let Flow recreate it, or keep it intentionally as a local override.");return a.push(`- Details command: ${Ke(e.version)}`),`${a.join(`
1652
1774
  `)}
1653
- `}async function ce(e=_()){let a=D(e),t=[],r=[],s;try{s=await re(a)}catch(n){if(n.code==="ENOENT")return{removed:t,kept:r};throw n}for(let n of s){if(n!=="flow"&&!n.startsWith("flow-"))continue;let d=u(a,n),p=await m(u(d,q));if(p===null){r.push(d);continue}let i=T(p),l=!1;for(let[v,o]of i){let c=await m(x(d,v));if(c!==null&&g(c)!==o){l=!0;break}}if(l){r.push(d);continue}await We(d,{recursive:!0,force:!0}),t.push(d)}return{removed:t,kept:r}}function I(){return["usage: opencode-plugin-flow <doctor|sync|uninstall> [options]","","commands:"," doctor Inspect managed Flow skills"," sync Install or refresh managed Flow skills"," uninstall Remove pristine Flow-owned managed skills","","doctor options:"," --json Write the doctor report as JSON"," --check, --strict Exit nonzero when doctor status is not ok","","global options:"," --help Show this help"," --version Print the plugin version"].join(`
1654
- `)}function $e(e,a){return e.every((t)=>a.has(t))}function Qe(e,a){if(a.json){process.stdout.write(`${JSON.stringify(e,null,2)}
1655
- `);return}process.stdout.write(ie(e))}async function Ke(e){let a=e[2],t=e.slice(3);if(a==="--help"||a==="-h"){process.stdout.write(`${I()}
1656
- `);return}if(a==="--version"||a==="-v"){process.stdout.write(`${F()}
1657
- `);return}if(a!=="uninstall"&&a!=="doctor"&&a!=="sync"){process.stderr.write(`${I()}
1658
- `),process.exitCode=2;return}if(a==="doctor"){if(!$e(t,new Set(["--json","--check","--strict"]))){process.stderr.write(`${I()}
1659
- `),process.exitCode=2;return}let n=await se();if(Qe(n,{json:t.includes("--json")}),(n.status==="sync_required"||n.status==="action_required")&&(t.includes("--check")||t.includes("--strict")))process.exitCode=1;return}if(t.length>0){process.stderr.write(`${I()}
1660
- `),process.exitCode=2;return}if(a==="sync"){let s=F(),n=await ne(s),d=n.filter((i)=>["installed","updated","updated_with_backup"].includes(i.action)),p=n.filter((i)=>i.action==="skipped_foreign");process.stdout.write(`Flow skill sync (${s})
1661
- `);for(let i of n){process.stdout.write(`- ${i.name}: ${i.action}
1662
- `);for(let l of i.backupPaths??[])process.stdout.write(` backup: ${l}
1775
+ `}async function ue(e=_()){let a=T(e),t=[],r=[],n;try{n=await ne(a)}catch(s){if(s.code==="ENOENT")return{removed:t,kept:r};throw s}for(let s of n){if(s!=="flow"&&!s.startsWith("flow-"))continue;let d=h(a,s),m=await f(h(d,D));if(m===null){r.push(d);continue}let c=P(m),l=!1;for(let[y,o]of c){let i=await f(b(d,y));if(i!==null&&v(i)!==o){l=!0;break}}if(l){r.push(d);continue}await ie(d,{recursive:!0,force:!0}),t.push(d)}return{removed:t,kept:r}}function R(){return["usage: opencode-plugin-flow <doctor|sync|uninstall> [options]","","commands:"," doctor Inspect managed Flow skills"," sync Install or refresh managed Flow skills"," uninstall Remove pristine Flow-owned managed skills","","doctor options:"," --json Write the doctor report as JSON"," --check, --strict Exit nonzero when doctor status is not ok","","global options:"," --help Show this help"," --version Print the plugin version"].join(`
1776
+ `)}function Ye(e,a){return e.every((t)=>a.has(t))}function Xe(e,a){if(a.json){process.stdout.write(`${JSON.stringify(e,null,2)}
1777
+ `);return}process.stdout.write(le(e))}async function Je(e){let a=e[2],t=e.slice(3);if(a==="--help"||a==="-h"){process.stdout.write(`${R()}
1778
+ `);return}if(a==="--version"||a==="-v"){process.stdout.write(`${I()}
1779
+ `);return}if(a!=="uninstall"&&a!=="doctor"&&a!=="sync"){process.stderr.write(`${R()}
1780
+ `),process.exitCode=2;return}if(a==="doctor"){if(!Ye(t,new Set(["--json","--check","--strict"]))){process.stderr.write(`${R()}
1781
+ `),process.exitCode=2;return}let s=await de();if(Xe(s,{json:t.includes("--json")}),(s.status==="sync_required"||s.status==="action_required")&&(t.includes("--check")||t.includes("--strict")))process.exitCode=1;return}if(t.length>0){process.stderr.write(`${R()}
1782
+ `),process.exitCode=2;return}if(a==="sync"){let n=I(),s=await ce(n),d=s.filter((c)=>["installed","updated","updated_with_backup"].includes(c.action)),m=s.filter((c)=>c.action==="skipped_foreign");process.stdout.write(`Flow skill sync (${n})
1783
+ `);for(let c of s){process.stdout.write(`- ${c.name}: ${c.action}
1784
+ `);for(let l of c.backupPaths??[])process.stdout.write(` backup: ${l}
1663
1785
  `)}if(d.length>0)process.stdout.write(`Restart OpenCode so the refreshed skill registry is used.
1664
- `);if(p.length>0)process.stdout.write(`Some managed skill folders are user-owned or edited; run doctor for repair guidance.
1665
- `);return}let r=await ce();for(let s of r.removed)process.stdout.write(`Removed Flow skill: ${s}
1666
- `);for(let s of r.kept)process.stdout.write(`Kept non-Flow or user-edited skill: ${s}
1786
+ `);if(m.length>0)process.stdout.write(`Some managed skill folders are user-owned or edited; run doctor for repair guidance.
1787
+ `);return}let r=await ue();for(let n of r.removed)process.stdout.write(`Removed Flow skill: ${n}
1788
+ `);for(let n of r.kept)process.stdout.write(`Kept non-Flow or user-edited skill: ${n}
1667
1789
  `);process.stdout.write(`Remove opencode-plugin-flow from your OpenCode plugin config and restart OpenCode.
1668
- `)}Ke(process.argv).catch((e)=>{process.stderr.write(`${e instanceof Error?e.message:String(e)}
1790
+ `)}Je(process.argv).catch((e)=>{process.stderr.write(`${e instanceof Error?e.message:String(e)}
1669
1791
  `),process.exitCode=1});