opencode-plugin-flow 4.1.16 → 4.1.17

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,5 +1,5 @@
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 S=`# 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
@@ -137,86 +137,21 @@ live-verified | test-verified | type-check-only | not-verified
137
137
 
138
138
  The manager must inspect and validate any candidate patch before recording Flow
139
139
  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
140
+ `;var W=`# Parallel orchestration
208
141
 
209
142
  Use fan-out when Flow work is broad enough that independent workers can gather
210
143
  evidence faster than one linear pass. The manager still owns the Flow session:
211
144
  only the manager calls state-changing Flow tools, approves plans, completes
212
145
  features, records reviews, or closes sessions.
213
146
 
214
- Read these companion references before a broad wave:
147
+ Read these companion references before a broad parallel pass:
215
148
 
149
+ - \`parallel-pass-patterns.md\` for pass selection, effort defaults, and stop or
150
+ follow-up rules.
216
151
  - \`handoff-format.md\` for the exact worker response shapes.
217
152
  - \`verification-gates.md\` for coverage checks, handoff acceptance, verifier
218
153
  triggers, and synthesis rules.
219
- - \`parallel-full-wave-example.md\` for a concrete end-to-end wave after the rules
154
+ - \`parallel-pass-example.md\` for a concrete end-to-end pass after the rules
220
155
  below are clear.
221
156
 
222
157
  ## Quick path
@@ -237,9 +172,9 @@ Read these companion references before a broad wave:
237
172
 
238
173
  - Prefer serial work when the scope is small, tightly coupled, or blocked by one
239
174
  decision that must be made before slices are meaningful.
240
- - A normal first wave is two to five workers with independent slices. Use more
175
+ - A normal first pass is two to five workers with independent slices. Use more
241
176
  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
177
+ - Run at most one routine follow-up pass. Extra passes need an explicit manager
243
178
  reason, such as a high-stakes verifier check or a newly discovered bounded
244
179
  slice.
245
180
  - Do not fan out just to keep agents busy. Every worker should reduce a known
@@ -274,7 +209,7 @@ Skip fan-out when:
274
209
  scope, and carry confidence labels.
275
210
  8. Send important low-confidence, single-source, contested, or citation-heavy
276
211
  claims to \`flow-verifier-worker\`.
277
- 9. Run second waves only for material gaps, conflicts, narrowed scope, or
212
+ 9. Run follow-up passes only for material gaps, conflicts, narrowed scope, or
278
213
  verification needs.
279
214
  10. Apply the manager synthesis barrier: keep only distilled, evidence-backed
280
215
  claims and synthesize one Flow artifact, such as plan fields, completion
@@ -363,7 +298,7 @@ Your exact slice: <paths, modules, command, claim ids, risk lens, or worktree>
363
298
  Expected coverage: <count, paths, range, or complete question set>
364
299
  Do: <bounded actions>
365
300
  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.
301
+ Return only the matching Flow handoff from handoff-format.md.
367
302
  \`\`\`
368
303
 
369
304
  For research or current-doc slices, require source checks for versioned or
@@ -390,11 +325,11 @@ the smallest check that can settle the disagreement.
390
325
 
391
326
  The manager synthesis barrier means raw handoffs do not move forward by default.
392
327
  Only claims that survived coverage, evidence, confidence, and verifier checks may
393
- enter the next wave, Flow payload, patch decision, or user-facing answer.
328
+ enter the next pass, Flow payload, patch decision, or user-facing answer.
394
329
 
395
- ## Second waves
330
+ ## Follow-up passes
396
331
 
397
- Start a follow-up wave when first-wave handoffs reveal:
332
+ Start a follow-up pass when first-pass handoffs reveal:
398
333
 
399
334
  - missing coverage in the original slice map.
400
335
  - conflicting findings that matter to the Flow decision.
@@ -403,8 +338,167 @@ Start a follow-up wave when first-wave handoffs reveal:
403
338
  - bounded implementation candidates after research converges.
404
339
 
405
340
  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
341
+ decides whether that is a follow-up pass and writes the next bounded prompt.
342
+ `;var O=`# Parallel pass example
343
+
344
+ Use this example after \`parallel-orchestration.md\` when a broad Flow task needs a
345
+ concrete pass shape.
346
+
347
+ Goal: review whether bundled Flow command guidance is self-contained and aligned
348
+ with hidden worker permissions.
349
+
350
+ Serial orientation: the manager reads \`src/config-shared.ts\` enough to identify
351
+ five public command templates and six hidden worker configs. The manager keeps
352
+ \`flow-status\` local because it is one line and does not need a worker.
353
+
354
+ Coverage gate: ten countable items remain after the local check.
355
+
356
+ - Slice A: \`flow-auto\`, \`flow-plan\`, and \`flow-run\` templates, expected 3/10.
357
+ - Slice B: \`flow-review\` template plus \`flow-reviewer\` config, expected 2/10.
358
+ - Slice C: remaining hidden worker permission blocks, expected 5/10 after
359
+ excluding the reviewer already covered by Slice B.
360
+
361
+ Worker prompts:
362
+
363
+ \`\`\`text
364
+ Overall goal, context only: confirm Flow public commands are self-contained.
365
+ Mode: evidence
366
+ Your exact slice: flow-auto, flow-plan, and flow-run templates in src/config-shared.ts.
367
+ Expected coverage: 3/3 templates.
368
+ Do: report bundled sections, setup preflight coverage, and any gaps with file:line evidence.
369
+ Do not: call state-changing Flow tools, edit .flow/**, own sibling slices, or make the final Flow verdict.
370
+ Return only the matching Flow handoff from handoff-format.md.
371
+ \`\`\`
372
+
373
+ \`\`\`text
374
+ Overall goal, context only: confirm Flow review command and hidden reviewer behavior.
375
+ Mode: review
376
+ Your exact slice: flow-review command template and flow-reviewer config in src/config-shared.ts.
377
+ Expected coverage: 2/2 surfaces.
378
+ Do: separate blocking findings from advisory notes and cite file:line evidence.
379
+ Do not: call state-changing Flow tools, edit .flow/**, own sibling slices, or make the final Flow verdict.
380
+ Return only the matching Flow handoff from handoff-format.md.
381
+ \`\`\`
382
+
383
+ \`\`\`text
384
+ Overall goal, context only: confirm hidden worker permissions match the orchestration model.
385
+ Mode: audit
386
+ 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.
387
+ Expected coverage: 5/5 worker permission blocks.
388
+ Do: report edit, bash, task, skill, flow_*, and flow_status permissions with evidence.
389
+ Do not: call state-changing Flow tools, edit .flow/**, own sibling slices, or make the final Flow verdict.
390
+ Return only the matching Flow handoff from handoff-format.md.
391
+ \`\`\`
392
+
393
+ Handoff checks: the manager accepts only reports with terminal status, matching
394
+ coverage counts, concrete file:line evidence, confidence tags, and claims inside
395
+ the assigned slice. A claim such as \`[high] validation workers may run commands;
396
+ evidence: src/config-shared.ts:307-320; corroboration: single source\` is usable.
397
+ A claim such as \`[high] permissions look safe; evidence: config reviewed\` is
398
+ dropped or retasked.
399
+
400
+ Verifier pass: the manager sends any single-source claim that will enter the
401
+ Flow payload to \`flow-verifier-worker\`, for example: \`C1: validation, audit,
402
+ candidate, and verifier workers have bash ask while evidence and review workers
403
+ have bash deny; sources: src/config-shared.ts worker permission blocks\`.
404
+
405
+ Final synthesis: the manager re-reads the relevant config lines, keeps only
406
+ verified or clearly labeled claims, and records one artifact such as a plan
407
+ decision, review payload, or docs patch. Raw handoffs and unverified suggestions
408
+ do not move into the next pass or user-facing answer.
409
+ `;var z=`# Parallel pass patterns
410
+
411
+ Flow uses parallel workers to reduce uncertainty, not to delegate decisions.
412
+ Each pass has a bounded purpose, an explicit coverage rule, and one
413
+ manager-owned synthesis result.
414
+
415
+ ## Choose a pass
416
+
417
+ | Situation | Flow pass | Output the manager may synthesize |
418
+ | --- | --- | --- |
419
+ | Repo shape is unclear before planning | Discovery pass | Requirements, decisions, targets, validation entries, or a review-first feature |
420
+ | A broad finding set needs refutation | Audit pass | Surviving findings with guards checked and gaps named |
421
+ | Changed files or risk lenses are too broad for one review pass | Review pass | One \`featureReview\` or \`finalReview\` payload owned by the manager |
422
+ | Test strategy or route coverage is unclear | Validation pass | Candidate commands or authorized raw command evidence |
423
+ | A claim is single-source, surprising, high-stakes, or payload-bound | Verification pass | Per-claim keep, narrow, rewrite, or remove decisions |
424
+ | Multiple implementation paths are plausible | Candidate pass | Candidate patches inspected and validated by the manager before use |
425
+
426
+ Prefer serial work when one file, command, or design question determines the
427
+ next step. A parallel pass should reduce a named planning, validation, review,
428
+ audit, or implementation uncertainty.
429
+
430
+ ## Pass Shapes
431
+
432
+ ### Discovery pass
433
+
434
+ Use before planning when the manager has oriented enough to name disjoint slices
435
+ but not enough to write reliable plan fields. Workers read specific modules,
436
+ routes, docs, commands, or risk lenses. The manager turns only evidenced claims
437
+ into plan fields.
438
+
439
+ ### Audit pass
440
+
441
+ Use when a report starts from candidate findings. Workers actively look for
442
+ guards, lifecycle resets, deployment constraints, and counterexamples before
443
+ reporting a finding. A finding that lacks refutation work stays advisory or
444
+ becomes a follow-up question.
445
+
446
+ ### Review pass
447
+
448
+ Use when changed files or risks can be reviewed independently. Review workers
449
+ separate blocking findings from advisory notes. The manager resolves conflicts,
450
+ checks cited artifacts, and returns one review payload.
451
+
452
+ ### Validation pass
453
+
454
+ Use when coverage is unclear or command evidence can be gathered independently.
455
+ Validation workers may run only manager-authorized commands and must report
456
+ exact command, status, raw outcome summary, coverage, confidence, and gaps.
457
+
458
+ ### Verification pass
459
+
460
+ Use for atomic claims. Give the verifier claim ids, cited sources or commands,
461
+ and the acceptance question. Do not ask a verifier to redesign the work or
462
+ review the whole feature.
463
+
464
+ ### Candidate pass
465
+
466
+ Use only with explicit user authorization plus isolated worktrees or exact
467
+ non-overlapping path ownership. Candidate patches are proposals until the
468
+ manager inspects, merges or rejects them, and validates the main workspace.
469
+
470
+ ## Effort Defaults
471
+
472
+ - Start with two to five workers. Use more only when the coverage gate is
473
+ countable and the manager can verify every handoff.
474
+ - Run at most one routine follow-up pass. Extra passes need a stated reason,
475
+ such as a high-stakes verification check or a newly discovered bounded slice.
476
+ - Spend effort where being wrong costs more: public API, persistence, security,
477
+ permissions, release behavior, data loss, and Flow payload claims.
478
+ - Do not fan out to keep agents busy. Worker setup and synthesis have real cost.
479
+
480
+ ## Stop And Extend
481
+
482
+ Stop after a pass when:
483
+
484
+ - the coverage rule is satisfied.
485
+ - accepted claims are evidenced, scoped, and confidence-labeled.
486
+ - material single-source, contested, high-stakes, or payload-bound claims have
487
+ been verified or downgraded.
488
+ - remaining gaps are explicit and do not block the Flow artifact being produced.
489
+
490
+ Start a bounded follow-up pass only when:
491
+
492
+ - the original slice map missed material scope.
493
+ - workers disagree on a claim that affects the Flow decision.
494
+ - a high-stakes or payload-bound claim needs verification.
495
+ - a first pass exposes a narrower implementation or validation slice worth
496
+ isolating.
497
+
498
+ The manager synthesis barrier applies after every pass: raw handoffs remain
499
+ candidate evidence until the manager checks coverage, resolves conflicts,
500
+ preserves confidence, and records one Flow-owned artifact.
501
+ `;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
502
 
409
503
  Verification is how Flow keeps parallel work from turning into parallel
410
504
  guesswork. Worker handoffs are candidate evidence; the manager decides what can
@@ -458,6 +552,25 @@ Use \`flow-verifier-worker\` when a claim is:
458
552
  Give the verifier atomic claims, cited sources or commands, and the acceptance
459
553
  question. Do not ask it to redesign the work or review the whole feature.
460
554
 
555
+ ## Verification tiers
556
+
557
+ Use the cheapest check that matches the risk:
558
+
559
+ - **Accept locally**: low-risk claims with direct evidence that the manager can
560
+ cheaply inspect or recount.
561
+ - **Verify once**: single-source, surprising, inferred, citation-heavy, or
562
+ Flow-payload-bound claims.
563
+ - **Verify strongly**: claims that affect security, persistence, permissions,
564
+ public API behavior, release behavior, data loss, or blocking review outcome.
565
+ Use independent verifier checks, manager-run commands, or direct artifact
566
+ inspection strong enough to settle the claim.
567
+ - **Do not accept**: claims without concrete evidence, claims outside the
568
+ assigned slice, claims contradicted by inspected artifacts, or claims where the
569
+ cited evidence supports only the topic rather than the assertion.
570
+
571
+ Verifier prompts should use stable claim ids, one atomic assertion per id, the
572
+ cited source or command for each id, and the exact acceptance question.
573
+
461
574
  ## Flow payload acceptance
462
575
 
463
576
  Planning fields may use worker evidence only when the source and scope are clear.
@@ -496,7 +609,7 @@ Before presenting or recording the result:
496
609
 
497
610
  \`Status: success\` only says the worker believes its slice is done. The manager
498
611
  still checks coverage and evidence before trusting the result.
499
- `;var E=`---
612
+ `;var V=`---
500
613
  name: flow
501
614
  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
615
  ---
@@ -518,7 +631,7 @@ Use Flow as a minimal state ledger, not as a framework. Skills provide judgment;
518
631
  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
632
  6. After all features are complete, archive the session with \`flow_session_close\` using \`kind: "completed"\`.
520
633
 
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.
634
+ 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
635
 
523
636
  Do not commit, push, amend, rebase, publish, or mutate releases during the
524
637
  autonomous Flow loop. Load \`flow-commit\` only when the user explicitly asks for
@@ -729,7 +842,7 @@ Weak evidence includes:
729
842
  - Public contracts and compatibility shims remain intact or were explicitly planned.
730
843
  - Deleted code is actually unreachable or obsolete.
731
844
  - Validation can catch a realistic mistake in the refactor.
732
- `;var V=`# Deslop smell rubric
845
+ `;var M=`# Deslop smell rubric
733
846
 
734
847
  Use this rubric to turn vague cleanup instincts into reviewable findings.
735
848
 
@@ -763,7 +876,7 @@ class; severity; location; evidence read; refutation checked; why it matters; sa
763
876
  \`\`\`
764
877
 
765
878
  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=`---
879
+ `;var L=`---
767
880
  name: flow-deslop
768
881
  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
882
  ---
@@ -805,11 +918,11 @@ For each claimed smell removal, verify:
805
918
  - **blast radius** — public contracts and downstream callers still work.
806
919
 
807
920
  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
921
+ `;var $=`# Parallel discovery
809
922
 
810
923
  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
924
 
812
- For broad waves, also load \`../../flow/references/parallel-orchestration.md\`.
925
+ For broad parallel passes, also load \`../../flow/references/parallel-orchestration.md\`.
813
926
  Use its pre-fan-out coverage gate and
814
927
  \`../../flow/references/handoff-format.md\` response shapes.
815
928
 
@@ -823,7 +936,7 @@ Use its pre-fan-out coverage gate and
823
936
 
824
937
  ## Flow repo default slices
825
938
 
826
- For this repository, good first-wave slices are:
939
+ For this repository, good first-pass slices are:
827
940
 
828
941
  - Runtime gates: \`src/runtime/schema.ts\`, \`src/runtime/transitions.ts\`,
829
942
  \`src/runtime/api.ts\`, and \`tests/runtime-gates.test.ts\`.
@@ -881,7 +994,7 @@ If workers disagree, inspect the source artifact yourself. If a candidate findin
881
994
  Apply the manager synthesis barrier from
882
995
  \`../../flow/references/verification-gates.md\`: only distilled, evidence-backed
883
996
  claims become plan fields.
884
- `;var $=`# Planning examples
997
+ `;var Q=`# Planning examples
885
998
 
886
999
  ## Rate limiting feature set
887
1000
 
@@ -966,7 +1079,7 @@ Better plan:
966
1079
  - Validation that only says "manual testing".
967
1080
  - Targets that name the entire repo.
968
1081
  - Features with hidden dependencies instead of \`dependsOn\`.
969
- `;var Q=`---
1082
+ `;var K=`---
970
1083
  name: flow-plan
971
1084
  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
1085
  ---
@@ -1036,7 +1149,7 @@ Use only \`finalReviewPolicy: "broad"\` or \`"detailed"\`. These are the canonic
1036
1149
  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
1150
 
1038
1151
  See \`references/planning-examples.md\` for payload examples and decomposition anti-patterns.
1039
- `;var K=`# Review rubric
1152
+ `;var Y=`# Review rubric
1040
1153
 
1041
1154
  Use this to decide whether a \`featureReview\` or \`finalReview\` payload may pass.
1042
1155
 
@@ -1124,7 +1237,7 @@ When reviewing a findings report, verify findings adversarially:
1124
1237
  - Downgrade or reject findings that do not survive refutation.
1125
1238
 
1126
1239
  Approve only on evidence actually inspected. A review is a claim of coverage, not a courtesy stamp.
1127
- `;var Y=`---
1240
+ `;var X=`---
1128
1241
  name: flow-review
1129
1242
  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
1243
  ---
@@ -1194,7 +1307,7 @@ Use \`status: "failed"\` when any blocking finding remains. Advisory findings ma
1194
1307
  \`finalReview\` payload.
1195
1308
 
1196
1309
  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
1310
+ `;var J=`# Audit findings rubric
1198
1311
 
1199
1312
  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
1313
 
@@ -1247,7 +1360,7 @@ follow-up order — correctness and persisted/user-input surfaces first
1247
1360
  \`\`\`
1248
1361
 
1249
1362
  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
1363
+ `;var Z=`# Validation evidence rubric
1251
1364
 
1252
1365
  Use this before recording \`flow_feature_complete\`.
1253
1366
 
@@ -1304,7 +1417,7 @@ Broad validation usually means the repo's full check command, full relevant test
1304
1417
  - If validation needs external access, missing credentials, or ambiguous user input, record \`status: "needs_input"\` with an honest \`outcome\`.
1305
1418
 
1306
1419
  Never trim failing output, relabel a failed command as passed, or use "not run" as completion evidence.
1307
- `;var Z=`---
1420
+ `;var H=`---
1308
1421
  name: flow-run
1309
1422
  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
1423
  ---
@@ -1391,7 +1504,7 @@ Complete with:
1391
1504
  \`\`\`
1392
1505
 
1393
1506
  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=`---
1507
+ `;var ee=`---
1395
1508
  name: flow-test
1396
1509
  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
1510
  ---
@@ -1515,7 +1628,7 @@ covered. Static inspection alone is a gap for behavioral changes.
1515
1628
 
1516
1629
  Never relabel a failed command as passed, invent output, or use "not run" as
1517
1630
  completion evidence.
1518
- `;var ee=`# UI quality rubric
1631
+ `;var ae=`# UI quality rubric
1519
1632
 
1520
1633
  Use this rubric for frontend planning, implementation, and review.
1521
1634
 
@@ -1559,7 +1672,7 @@ class; severity; location or screenshot area; evidence inspected; user impact; f
1559
1672
  \`\`\`
1560
1673
 
1561
1674
  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
1675
+ `;var te=`# Visual verification workflow
1563
1676
 
1564
1677
  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
1678
 
@@ -1599,7 +1712,7 @@ Record the reason and use the strongest available substitute:
1599
1712
  - code inspection against existing component patterns.
1600
1713
 
1601
1714
  Do not claim visual polish was verified if no visual artifact was inspected.
1602
- `;var te=`---
1715
+ `;var oe=`---
1603
1716
  name: flow-ui-quality
1604
1717
  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
1718
  ---
@@ -1647,23 +1760,23 @@ Approve only when the interface is both useful and inspectable:
1647
1760
  - Screenshot/browser evidence supports the claim whenever feasible.
1648
1761
 
1649
1762
  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(`
1763
+ `;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:S},{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(`
1764
+ `)}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 g=d.get(i.relativePath);if(p!==null&&(g?v(p)!==g:s!==null))l.push(await re(u,p))}for(let[i,u]of d){if(y.has(i))continue;let p=b(r,i),g=await f(p);if(g===null)continue;if(c=!0,v(g)!==u)l.push(await re(p,g));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),g=P(u);if(await f(h(i,"SKILL.md"))===null)return{name:o.name,path:i,status:"missing",markerVersion:p,missingFiles:o.files.map((w)=>w.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 w of o.files){let q=await f(b(i,w.relativePath));if(q===null){U.push(w.relativePath);continue}if(q===w.content)continue;let j=g.get(w.relativePath);if(j&&v(q)!==j){A.push(w.relativePath);continue}C.push(w.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
1765
  `)}
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}
1766
+ `}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(`
1767
+ `)}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)}
1768
+ `);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()}
1769
+ `);return}if(a==="--version"||a==="-v"){process.stdout.write(`${I()}
1770
+ `);return}if(a!=="uninstall"&&a!=="doctor"&&a!=="sync"){process.stderr.write(`${R()}
1771
+ `),process.exitCode=2;return}if(a==="doctor"){if(!Ye(t,new Set(["--json","--check","--strict"]))){process.stderr.write(`${R()}
1772
+ `),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()}
1773
+ `),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})
1774
+ `);for(let c of s){process.stdout.write(`- ${c.name}: ${c.action}
1775
+ `);for(let l of c.backupPaths??[])process.stdout.write(` backup: ${l}
1663
1776
  `)}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}
1777
+ `);if(m.length>0)process.stdout.write(`Some managed skill folders are user-owned or edited; run doctor for repair guidance.
1778
+ `);return}let r=await ue();for(let n of r.removed)process.stdout.write(`Removed Flow skill: ${n}
1779
+ `);for(let n of r.kept)process.stdout.write(`Kept non-Flow or user-edited skill: ${n}
1667
1780
  `);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)}
1781
+ `)}Je(process.argv).catch((e)=>{process.stderr.write(`${e instanceof Error?e.message:String(e)}
1669
1782
  `),process.exitCode=1});