opencode-plugin-flow 3.3.13 → 3.3.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/README.md +8 -2
- package/dist/cli.js +2 -2
- package/dist/index.js +24 -24
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,14 @@ the rejected alternatives, and the validation that was run — see
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [3.3.15] - 2026-06-14
|
|
10
|
+
|
|
11
|
+
Clarify derived signal authority so readiness blockers stay operational, context quality stays advisory, and context packs carry the same handoff contract.
|
|
12
|
+
|
|
13
|
+
## [3.3.14] - 2026-06-14
|
|
14
|
+
|
|
15
|
+
Delete stale architecture/test/docs scaffolding that only protected retired prompt/audit history or implementation-shape assertions, with no runtime or public surface change.
|
|
16
|
+
|
|
9
17
|
## [3.3.13] - 2026-06-14
|
|
10
18
|
|
|
11
19
|
Remove v2 session-resume compatibility, tighten retired-key payload parsing, shrink the current maintainer contract, and drop empty `core`/`workflow` owners from seam enforcement.
|
package/README.md
CHANGED
|
@@ -31,7 +31,7 @@ Add Flow to the `plugin` array in your `opencode.json` (global `~/.config/openco
|
|
|
31
31
|
|
|
32
32
|
```json
|
|
33
33
|
{
|
|
34
|
-
"plugin": ["opencode-plugin-flow@3.3.
|
|
34
|
+
"plugin": ["opencode-plugin-flow@3.3.15"]
|
|
35
35
|
}
|
|
36
36
|
```
|
|
37
37
|
|
|
@@ -153,7 +153,13 @@ Plus: atomic, locked, path-safe writes under `.flow/**`; schema validation of al
|
|
|
153
153
|
|
|
154
154
|
Everything judgment-shaped — how to decompose a plan, how deep to review, what counts as good evidence, when to stop and ask — lives in the skills, where you can read and override it.
|
|
155
155
|
|
|
156
|
-
|
|
156
|
+
Flow uses three authority levels for derived status signals:
|
|
157
|
+
|
|
158
|
+
- **Hard gate** — runtime rejects the action. The completion and persistence gates above are hard gates.
|
|
159
|
+
- **Workflow blocker** — derived status says the agent should not proceed until the issue is resolved or explicitly justified. `workflowReadiness.state` values such as `blocked_by_context`, `blocked_by_validation`, and `blocked_by_review` are workflow blockers, not persisted state or runtime invariants.
|
|
160
|
+
- **Advisory diagnostic** — useful planning or review signal, but judgment-owned. `contextQuality` and broad/weak-context diagnostics are advisory unless they expose concrete drift that readiness reports as blocked.
|
|
161
|
+
|
|
162
|
+
`/flow-status` also reports derived `workflowReadiness`, `contextQuality`, `contextTraceability`, and `contextDiagnostics`. These fields show whether the session is ready for planning, execution, feature review, final review, or release; how strong the planned context is; which planned targets changed; which validation and review evidence exists; and where planned context is weak. `flow_context` exposes the same derived handoff in summary, feature, or full views, optionally with a lightweight project structure map. They do not replace review judgment, but they make context gaps visible before they become unverifiable completion claims.
|
|
157
163
|
|
|
158
164
|
## What Flow writes
|
|
159
165
|
|
package/dist/cli.js
CHANGED
|
@@ -13,7 +13,7 @@ ${e.template}
|
|
|
13
13
|
`)}
|
|
14
14
|
|
|
15
15
|
${e.prompt}
|
|
16
|
-
`}function L(){return new Map(Object.entries(W).map(([e,t])=>[e,D(t)]))}function
|
|
16
|
+
`}function L(){return new Map(Object.entries(W).map(([e,t])=>[e,D(t)]))}function Q(){return new Map(Object.entries(j).map(([e,t])=>[e,ee(t)]))}async function G(e){let t=[],i=[];for(let a of e.names){let s=U(e.root,`${a}.md`),o=U(e.root,`.${a}.flow-version`),n=await V(o),r=n===null?null:b(n,e.kind,a);if(r===null)continue;let d=await V(s);if(d!==null&&p(d)!==r.hash){i.push(s);continue}if(!e.dryRun)await F(s,{force:!0}),await F(o,{force:!0}),await F(`${s}.backup`,{force:!0});t.push(s)}return{removed:t,keptUserEdited:i}}async function V(e){try{return await $(e,"utf8")}catch(t){if(t.code==="ENOENT")return null;throw t}}function te(e){if(!e)return[];let t=["permission:"];for(let[i,a]of Object.entries(e)){if(typeof a==="string"){t.push(` ${JSON.stringify(i)}: ${JSON.stringify(a)}`);continue}if(a&&typeof a==="object"){t.push(` ${JSON.stringify(i)}:`);for(let[s,o]of Object.entries(a))t.push(` ${JSON.stringify(s)}: ${JSON.stringify(o)}`)}}return t}async function Y({homeDir:e,dryRun:t=!1,logger:i}){let a={removedSkills:[],keptUserEditedSkills:[],removedCommands:[],keptUserEditedCommands:[],removedAgents:[],keptUserEditedAgents:[],removedPreNpmPlugin:null,keptForeignPreNpmPlugin:null},s=c(e,x);for(let d of await le(s)){if(d!=="flow"&&!d.startsWith("flow-"))continue;let l=c(s,d),u=await de(l);if(u==="foreign")continue;if(u==="user_edited"){a.keptUserEditedSkills.push(l),i?.(`Kept user-edited Flow skill at ${l}; remove it manually if it is no longer needed.`);continue}if(!t)await ce(l);a.removedSkills.push(l),i?.(`${t?"Would remove":"Removed"} Flow skill at ${l}.`)}let o=await G({kind:"command",root:c(e,g),names:k,dryRun:t});for(let d of o.removed)a.removedCommands.push(d),i?.(`${t?"Would remove":"Removed"} retired Flow command at ${d}.`);for(let d of o.keptUserEdited)a.keptUserEditedCommands.push(d),i?.(`Kept user-edited Flow command at ${d}; remove it manually if it is no longer needed.`);await C({homeDir:e,dryRun:t,logger:i,kind:"command",root:c(e,g),files:L(),removed:a.removedCommands,keptUserEdited:a.keptUserEditedCommands}),await C({homeDir:e,dryRun:t,logger:i,kind:"agent",root:c(e,_),files:Q(),removed:a.removedAgents,keptUserEdited:a.keptUserEditedAgents});let n=c(e,R),r=await f(n);if(r!==null)if(r.startsWith(A)){if(!t)await h(n,{force:!0});a.removedPreNpmPlugin=n,i?.(`${t?"Would remove":"Removed"} pre-npm Flow plugin copy at ${n}.`)}else a.keptForeignPreNpmPlugin=n,i?.(`Kept ${n}: it is not managed by Flow. Remove it manually if it is a stale Flow copy.`);return i?.('Finally, remove "opencode-plugin-flow" from the plugin array in opencode.json and restart OpenCode.'),a}async function de(e){let t=c(e,"SKILL.md"),i=await f(t),a=await f(c(e,w)),s=a===null?null:T(a);if(s!==null&&a!==null){for(let[r,d]of y(a)){if(r==="SKILL.md")continue;let l=M(e,r);if(l===null)continue;let u=await f(l);if(u!==null&&p(u)!==d)return"user_edited"}if(i===null)return"pristine";if(s.hash!==null&&p(i)===s.hash)return"pristine";return m(i).kind==="valid_generated"?"pristine":"user_edited"}if(i===null)return"foreign";let o=m(i);if(o.kind==="valid_generated")return"pristine";if(o.kind==="invalid_generated")return"user_edited";return"foreign"}function M(e,t){let i=ne(c(e,...t.split("/")));if(i!==e&&i.startsWith(`${e}${re}`))return i;return null}async function ce(e){let t=await f(c(e,w)),i=new Set;if(t!==null)for(let a of y(t).keys()){let s=M(e,a);if(s===null)continue;await h(s,{force:!0}),await h(`${s}.backup`,{force:!0});let o=oe(s);if(o!==e)i.add(o)}await h(c(e,"SKILL.md"),{force:!0}),await h(c(e,w),{force:!0}),await h(c(e,N),{force:!0});for(let a of[...i].sort((s,o)=>o.length-s.length))await I(a);await I(e)}async function I(e){try{await se(e)}catch(t){let i=t.code;if(i!=="ENOENT"&&i!=="ENOTEMPTY")throw t}}async function le(e){try{return(await ae(e,{withFileTypes:!0})).filter((i)=>i.isDirectory()).map((i)=>i.name).sort()}catch(t){if(t.code==="ENOENT")return[];throw t}}async function f(e){try{return await ie(e,"utf8")}catch(t){if(t.code==="ENOENT")return null;throw t}}async function C(e){for(let[t,i]of e.files){let a=c(e.root,`${t}.md`),s=c(e.root,`.${t}.flow-version`),o=await f(a),n=await f(s),r=n===null?null:b(n,e.kind,t);if(o===null&&r===null)continue;if(!(r!==null||o===i))continue;if(o!==null&&r!==null&&p(o)!==r.hash){e.keptUserEdited.push(a),e.logger?.(`Kept user-edited Flow ${e.kind} at ${a}; remove it manually if it is no longer needed.`);continue}if(!e.dryRun)await h(a,{force:!0}),await h(s,{force:!0}),await h(`${a}.backup`,{force:!0});e.removed.push(a),e.logger?.(`${e.dryRun?"Would remove":"Removed"} Flow ${e.kind} at ${a}.`)}if(!e.dryRun)await I(e.root)}var q=`opencode-plugin-flow — Flow plugin lifecycle commands
|
|
17
17
|
|
|
18
18
|
Usage:
|
|
19
19
|
bunx opencode-plugin-flow uninstall [--dry-run]
|
|
@@ -32,4 +32,4 @@ Options:
|
|
|
32
32
|
|
|
33
33
|
${q}`),1;let a=!1;for(let s of t){if(s==="--dry-run"){a=!0;continue}return S(`Unknown argument: ${s}
|
|
34
34
|
|
|
35
|
-
${q}`),1}return await
|
|
35
|
+
${q}`),1}return await Y({homeDir:process.env.HOME??he(),dryRun:a,logger:X}),0}try{process.exitCode=await ue(process.argv.slice(2))}catch(e){S(e instanceof Error?e.message:String(e)),process.exitCode=1}
|