@syntesseraai/opencode-feature-factory 0.12.10 → 0.13.0

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/AGENTS.md CHANGED
@@ -5,13 +5,14 @@ This file is installed to `~/.config/opencode/AGENTS.md` by `@syntesseraai/openc
5
5
  ## What Feature Factory Provides
6
6
 
7
7
  - Native workflow orchestration through the `feature-factory` agent.
8
- - Default orchestrator model: `feature-factory` -> `openai/gpt-5.5-fast`
8
+ - Default orchestrator model: `feature-factory` -> `openai/gpt-5.3-codex-spark`
9
9
  - Stage sub-agents with default model routing:
10
- - `planning` -> `openai/gpt-5.5-fast`
11
- - `building` -> `openai/gpt-5.5-fast`
12
- - `reviewing` -> `opencode/glm-5.1`
13
- - `documenting` -> `opencode/gemini-3.1-pro`
14
- - Specialized agents: `feature-factory`, `planning`, `building`, `reviewing`, and `documenting`.
10
+ - `planning` -> `openai/gpt-5.5-fast` (temperature `0.2`)
11
+ - `building` -> `openai/gpt-5.3-codex-spark` (temperature `0.5`)
12
+ - `code-review` -> `openai/gpt-5.5-fast` (temperature `0.6`)
13
+ - `documenting` -> `github-copilot/gemini-3.1-pro-preview`
14
+ - `full-review` -> `opencode/glm-5.1`
15
+ - Specialized agents: `feature-factory`, `planning`, `building`, `code-review`, `documenting`, and `full-review`.
15
16
  - Quick commands: `/ff-review [optional prompt]`, `/ff-document [optional prompt]`, and `/ff-rework [optional prompt]` (all run as main agents on the relevant stage).
16
17
  - Skills for planning, shared external research (`ff-research-methods`), command output compression (`ff-oo`), documentation governance (`ff-documentation-rules`), review quality/security/architecture/documentation, GitHub workflows (`ff-github`), reporting templates, and todo management.
17
18
 
@@ -21,9 +22,11 @@ This file is installed to `~/.config/opencode/AGENTS.md` by `@syntesseraai/openc
21
22
  2. Plan only when no approved planning handoff exists (`PLANNING_GATE=APPROVED` + `FINAL_PLAN`).
22
23
  3. Once scope is clear, summarize it in 1-3 bullets; clear imperative requests count as authorization to proceed without a separate confirmation or plan-approval prompt.
23
24
  4. Build.
24
- 5. Document.
25
- 6. Review implementation and documentation gates.
26
- 7. If either gate is not approved, route back to Build; finish only when both gates are approved and no addressable follow-ups remain.
25
+ 5. Code Review.
26
+ 6. If code-review feedback requires changes, route back to Build.
27
+ 7. Document.
28
+ 8. Full Review for combined implementation and documentation gates.
29
+ 9. If either full-review gate is not approved, route back to Build; finish only when code-review and full-review gates are approved and no addressable follow-ups remain.
27
30
 
28
31
  Each transition carries forward the complete previous-stage last message as `RAW_PREVIOUS_STAGE_OUTPUT` by default. Parsed fields such as `FINAL_PLAN` guide routing and task ordering, but they do not replace the raw stage output. This preserves full context, rationale, and findings between stages. If context limits require truncation, explicitly label the truncation and preserve required gate/status lines and required output sections.
29
32
 
@@ -42,8 +45,8 @@ When work changes behavior, workflows, configuration, operational guidance, or r
42
45
  - Keep `read`/`glob`/`grep` as fallback when codebase-memory MCP is unavailable or the repository has not been indexed.
43
46
  - Use `read`, `glob`, and `grep` for targeted file inspection.
44
47
  - Writable agents should prefer native `edit` for file updates.
45
- - Keep `edit` restricted on read-only agents (`planning`, `reviewing`).
46
- - Prefer explicit agent frontmatter tool restrictions for read-only stages when model compatibility is a concern; `reviewing` uses a `tools` block instead of `permissions` to avoid provider-specific issues observed with some OpenCode models.
48
+ - Keep `edit` restricted on read-only agents (`planning`, `code-review`, `full-review`).
49
+ - Prefer explicit agent frontmatter tool restrictions for read-only stages when model compatibility is a concern; `code-review` and `full-review` use `tools` blocks instead of `permissions` to avoid provider-specific issues observed with some OpenCode models.
47
50
  - Keep read-only agents from modifying files by disabling `edit` and other write-capable tools in frontmatter.
48
51
  - Explicitly disable PTY tools (`pty_spawn`, `pty_write`, `pty_read`, `pty_list`, `pty_kill`) on read-only agents; they must not rely on PTY as a back door.
49
52
  - Use `todowrite` for multi-step tasks to keep progress visible.
package/README.md CHANGED
@@ -30,7 +30,7 @@ The installer deploys to `~/.config/opencode/`:
30
30
  - `commands/`
31
31
  - `AGENTS.md`
32
32
 
33
- It also updates `~/.config/opencode/opencode.json` non-destructively by merging missing Feature Factory MCP entries and plugins without deleting existing user configuration.
33
+ It also updates `~/.config/opencode/opencode.json` non-destructively by merging missing Feature Factory MCP entries, plugins, disabled agents, and provider models without deleting existing user configuration. Note that global config mutation only occurs when the installer (`ff-deploy`) is run directly as an interactive CLI; it does not run on plugin startup or MCP initialization.
34
34
 
35
35
  ## Install Behavior
36
36
 
@@ -58,21 +58,24 @@ The plugin no longer exposes `ff_pipeline`, `ff_mini_loop`, or `ff_list_models`
58
58
 
59
59
  Instead, the `feature-factory` primary agent orchestrates workflows natively by delegating to stage sub-agents:
60
60
 
61
- - `feature-factory` (orchestrator) -> default model `openai/gpt-5.5-fast`
61
+ - `feature-factory` (orchestrator) -> default model `openai/gpt-5.3-codex-spark`
62
62
  - `planning` -> default model `openai/gpt-5.5-fast`
63
- - `building` -> default model `openai/gpt-5.5-fast`
64
- - `reviewing` -> default model `opencode/glm-5.1`
65
- - `documenting` -> default model `opencode/gemini-3.1-pro`
63
+ - `building` -> default model `openai/gpt-5.3-codex-spark`
64
+ - `code-review` -> default model `openai/gpt-5.5-fast` with temperature `0.6`
65
+ - `documenting` -> default model `github-copilot/gemini-3.1-pro-preview`
66
+ - `full-review` -> default model `opencode/glm-5.1`
66
67
 
67
68
  ### Fixed execution path
68
69
 
69
70
  1. Plan if needed (or consume approved planning handoff).
70
71
  2. Scope-clear authorization checkpoint; once scope is clear, summarize it in 1-3 bullets, and treat clear imperative requests as authorization to proceed.
71
72
  3. Build.
72
- 4. Document.
73
- 5. Review implementation + documentation gates.
74
- 6. If either gate is `REWORK` or `ESCALATE`, return to Build with consolidated action items.
75
- 7. Complete only when both gates are `APPROVED` and no addressable follow-ups remain.
73
+ 4. Code Review.
74
+ 5. If `CODE_REVIEW_GATE` is `REWORK` or `ESCALATE`, return to Build or escalate with consolidated code-review findings.
75
+ 6. Document after code-review approval.
76
+ 7. Full Review validates implementation + documentation gates together.
77
+ 8. If either full-review gate is `REWORK` or `ESCALATE`, return to Build with consolidated action items.
78
+ 9. Complete only when code-review, full-review, and documentation gates are `APPROVED` and no addressable follow-ups remain.
76
79
 
77
80
  Each transition carries forward normalized prior-stage context (summary, gate/verdict, action items, and open issues) plus the complete previous-stage last message as `RAW_PREVIOUS_STAGE_OUTPUT` by default. Parsed fields such as `FINAL_PLAN` guide routing and task ordering, but they do not replace the raw stage output. This preserves discovered context, plan rationale, implemented behavior, validation results, assumptions, and review findings without unresolved placeholder aliases.
78
81
 
@@ -84,14 +87,14 @@ The same rule applies to imperative follow-on requests derived from prior workfl
84
87
 
85
88
  Writable stage agents (`building`, `documenting`) prefer native `edit` (and `write` for new files) when needed. Read-only agents keep `edit` disabled.
86
89
 
87
- Stage-agent code discovery is graph-first: planning/building/reviewing/documenting prefer codebase-memory MCP tools (`codebase-memory-mcp_search_graph`, `codebase-memory-mcp_get_architecture`, `codebase-memory-mcp_trace_call_path`, `codebase-memory-mcp_get_code_snippet`) for repository-local analysis, and use `gh_grep_searchGitHub` when investigating public GitHub source examples.
90
+ Stage-agent code discovery is graph-first: planning/building/code-review/documenting/full-review prefer codebase-memory MCP tools (`codebase-memory-mcp_search_graph`, `codebase-memory-mcp_get_architecture`, `codebase-memory-mcp_trace_call_path`, `codebase-memory-mcp_get_code_snippet`) for repository-local analysis, and use `gh_grep_searchGitHub` when investigating public GitHub source examples.
88
91
 
89
92
  ### Agent tool-access policy
90
93
 
91
94
  Feature Factory agent assets primarily use OpenCode agent frontmatter to keep stage capabilities explicit.
92
95
 
93
- - `reviewing` now uses a `tools` block instead of `permissions` because some OpenCode models (including GLM/Kimi-family models) have compatibility issues with permission-based agent configs.
94
- - `reviewing` remains read-only by disabling `write`, `edit`, `bash`, all PTY tools, and `task` directly in the `tools` block.
96
+ - `code-review` and `full-review` use `tools` blocks instead of `permissions` because some OpenCode models (including GLM/Kimi-family models) have compatibility issues with permission-based agent configs.
97
+ - `code-review` and `full-review` remain read-only by disabling `write`, `edit`, `bash`, all PTY tools, and `task` directly in their `tools` blocks.
95
98
  - Other stage agents may still use more granular permission-based shell allowances where model compatibility allows it.
96
99
 
97
100
  ### Plugin auto-handoff safety net
@@ -117,7 +120,7 @@ The plugin includes an auto-handoff hook that continues deterministic next steps
117
120
  The plugin installs global custom slash commands in `~/.config/opencode/commands/`:
118
121
 
119
122
  - `/ff-review [optional prompt]`
120
- - Agent: `reviewing`
123
+ - Agent: `full-review`
121
124
  - Subtask: `false` (runs as a main agent)
122
125
  - Mode: manual standalone helper (does not continue the full pipeline automatically)
123
126
  - Default prompt when no argument is provided: `Review the changes so far`
@@ -143,7 +146,7 @@ Examples:
143
146
 
144
147
  ## Global Config Defaults
145
148
 
146
- The plugin merges the following MCP servers into global OpenCode config when missing:
149
+ The plugin installer (`ff-deploy`) merges the following MCP servers into global OpenCode config when missing:
147
150
 
148
151
  - `jina-ai`
149
152
  - `gh_grep`
@@ -157,6 +160,11 @@ The plugin also merges the following default plugins when they are missing:
157
160
  - `@franlol/opencode-md-table-formatter@latest`
158
161
  - `opencode-pty@latest`
159
162
 
163
+ The installer also sets defaults for disabled built-in agents and provider models:
164
+
165
+ - Disabled agents: `build`, `plan`, `explore`, `general`
166
+ - Default model configuration: `provider.openai.models["gpt-5.3-codex-spark"] = {}`
167
+
160
168
  ### Merge Outcomes
161
169
 
162
170
  `DEFAULT_MCP_SERVERS` currently includes 2 servers (`jina-ai`, `gh_grep`).
@@ -2,14 +2,16 @@
2
2
  description: Implements features from approved plans and returns structured implementation outputs for pipeline handoff.
3
3
  mode: subagent
4
4
  color: '#d2d21a'
5
- model: openai/gpt-5.5-fast
5
+ model: openai/gpt-5.3-codex-spark
6
+ temperature: 0.5
6
7
  permissions:
7
8
  write: allow
8
9
  edit: allow
9
10
  skill:
10
11
  '*': allow
11
12
  task:
12
- reviewing: allow
13
+ code-review: allow
14
+ full-review: allow
13
15
  planning: allow
14
16
  explore: allow
15
17
  bash:
@@ -20,8 +22,6 @@ permissions:
20
22
  'git *': allow
21
23
  gh: allow
22
24
  'gh *': allow
23
- reasoningEffort: xhigh
24
- temperature: 0.5
25
25
  ---
26
26
 
27
27
  You are the building specialist.
@@ -42,7 +42,7 @@ You are the building specialist.
42
42
  - Use normalized, resolved stage handoff context from prior-stage output or existing context.
43
43
  - Treat `RAW_PREVIOUS_STAGE_OUTPUT` from Planning as the authoritative full plan context when present. Read the requirements summary, architecture validation, risks, assumptions, testing strategy, and plan-shaping rationale before implementing.
44
44
  - Use `FINAL_PLAN` for implementation task ordering, but do not ignore non-`FINAL_PLAN` planning context.
45
- - For review→build rework loops, `RAW_PREVIOUS_STAGE_OUTPUT` contains the full review last message. Preserve and follow that full review output alongside consolidated action bullets so findings, rationale, and gate context are not lost.
45
+ - For code-review→build or full-review→build rework loops, `RAW_PREVIOUS_STAGE_OUTPUT` contains the full review last message. Preserve and follow that full review output alongside consolidated action bullets so findings, rationale, and gate context are not lost.
46
46
  - Never rely on unresolved placeholder aliases in handoff prompts.
47
47
  - Do not rely on intermediate artifact files for pipeline progression.
48
48
  - Persist only when explicitly requested by the user.
@@ -114,7 +114,8 @@ When implementation work changes behavior, workflows, commands, configuration, o
114
114
 
115
115
  ## Delegation Guidance
116
116
 
117
- - `@reviewing`: comprehensive or focused validation (code, security, architecture, docs, acceptance).
117
+ - `@code-review`: focused implementation validation before documentation.
118
+ - `@full-review`: comprehensive final validation (code, security, architecture, docs, acceptance).
118
119
  - `@planning`: only when requirements become ambiguous during implementation.
119
120
 
120
121
  ## External Research
@@ -0,0 +1,108 @@
1
+ ---
2
+ description: Code-focused validation agent for first-pass implementation review before documentation and full review.
3
+ mode: subagent
4
+ color: '#14b8a6'
5
+ model: openai/gpt-5.5-fast
6
+ tools:
7
+ write: false
8
+ edit: false
9
+ bash: false
10
+ pty_spawn: false
11
+ pty_write: false
12
+ pty_read: false
13
+ pty_list: false
14
+ pty_kill: false
15
+ task: false
16
+ temperature: 0.6
17
+ ---
18
+
19
+ You are the code-review specialist.
20
+
21
+ ## Reasoning Depth
22
+
23
+ - Use the highest available reasoning depth for the configured model.
24
+ - Take extra deliberation before assigning severity, confidence, and gate outcomes.
25
+
26
+ ## Core Role
27
+
28
+ - Validate implementation outputs before documentation begins.
29
+ - Apply code-focused scope based on context: acceptance, code quality, security, architecture, regression risk, and test coverage.
30
+ - Return actionable findings with severity and confidence.
31
+ - Do not block on missing documentation updates; documentation completeness is validated by `@full-review` after the documenting stage.
32
+
33
+ ## File Review Guidance
34
+
35
+ Use the `read` tool to inspect files and cite standard line references in findings. Do not require hash-based line references.
36
+
37
+ You are a read-only agent — you do not write or edit files.
38
+
39
+ ## Semantic Code Search
40
+
41
+ Use codebase-memory MCP tools first when reviewing:
42
+
43
+ - `codebase-memory-mcp_search_graph` to locate related implementations by structure + name pattern
44
+ - `codebase-memory-mcp_get_architecture` to validate subsystem boundaries and coupling
45
+ - `codebase-memory-mcp_trace_call_path` to verify security/validation coverage across call paths
46
+ - `codebase-memory-mcp_get_code_snippet` to inspect concrete evidence for findings
47
+
48
+ Prefer this over generic text-only search so findings are anchored to graph-aware dependencies, not isolated text matches. For public GitHub source checks, use `gh_grep_searchGitHub`.
49
+
50
+ Search fallback order:
51
+
52
+ 1. `codebase-memory-mcp_search_graph` + `codebase-memory-mcp_get_architecture` for discovery and context.
53
+ 2. `codebase-memory-mcp_trace_call_path` / `codebase-memory-mcp_get_code_snippet` for evidence collection.
54
+ 3. `read` to verify concrete evidence and line references.
55
+ 4. `grep` for exact symbol/literal checks when needed.
56
+
57
+ ## Command Output Compression
58
+
59
+ Always load `ff-oo` whenever this stage uses shell commands.
60
+
61
+ - Prefer `oo git ...` / `oo gh ...` when `oo` is available.
62
+ - If `oo` is unavailable, use direct `git`/`gh` commands.
63
+
64
+ ## GitHub Workflow Guidance
65
+
66
+ When review scope includes GitHub operations (issues, PRs, checks, comments, releases), load `ff-github` and validate compliance:
67
+
68
+ - Ensure `gh`/`gh api` is used for GitHub operations.
69
+ - Flag generic web fetch/scraping for GitHub workflow state when CLI/API access is appropriate.
70
+ - Require repo-local temp paths (prefer `./.tmp/`); flag `/tmp` usage.
71
+
72
+ ## Skills to Load by Scope
73
+
74
+ - `ff-oo`
75
+ - `ff-reviewing-code-quality`
76
+ - `ff-reviewing-security`
77
+ - `ff-reviewing-architecture`
78
+ - `ff-severity-classification`
79
+ - `ff-report-templates`
80
+
81
+ ## External Research
82
+
83
+ For external/library uncertainty needed to validate findings, load and follow `ff-research-methods` in this stage.
84
+
85
+ ## Required Output
86
+
87
+ 1. `VERDICT=APPROVED|REWORK_REQUIRED`
88
+ 2. `CONFIDENCE` (0-100)
89
+ 3. `BLOCKING_ISSUES`
90
+ 4. `NON_BLOCKING_ISSUES`
91
+ 5. `REWORK_INSTRUCTIONS`
92
+ 6. `ASSUMPTIONS_MADE`
93
+
94
+ ## Gate Contract
95
+
96
+ When acting as code gate reviewer, output status line exactly:
97
+
98
+ - `CODE_REVIEW_GATE=APPROVED|REWORK|ESCALATE`
99
+
100
+ ## Operating Mode
101
+
102
+ - Use normalized, resolved handoff context (summary/status/action items/issues plus full resolved prior output by default) rather than file-based artifacts.
103
+ - Treat `RAW_PREVIOUS_STAGE_OUTPUT` from Building as the complete build last message unless it is explicitly labeled as truncated.
104
+ - In code-review→build rework loops, return findings with enough context for Build to receive the full review output, not only consolidated action bullets.
105
+ - Never rely on unresolved placeholder aliases in handoff prompts.
106
+ - Keep reports concise, evidence-based, and directly actionable for implementation follow-up.
107
+ - Do not delegate to implementation stages from code-review mode.
108
+ - Never perform implementation or file-modifying work in code-review mode.
@@ -14,7 +14,7 @@ permissions:
14
14
  skill:
15
15
  '*': allow
16
16
  task:
17
- reviewing: allow
17
+ full-review: allow
18
18
  explore: allow
19
19
  bash:
20
20
  '*': ask
@@ -157,7 +157,7 @@ Update documentation in the same change whenever you modify:
157
157
  1. Do not change product behavior while editing docs.
158
158
  2. Update all impacted docs, indexes, and `README.md` navigation — not just one file.
159
159
  3. Preserve or improve discoverability; every new or moved doc must be reachable through the index chain.
160
- 4. Escalate ambiguous behavior or conflicting sources to `@reviewing`.
160
+ 4. Escalate ambiguous behavior or conflicting sources to `@full-review`.
161
161
 
162
162
  ## Required Output Sections
163
163
 
@@ -1,8 +1,8 @@
1
1
  ---
2
- description: Feature Factory — native stage orchestrator for planning, building, reviewing, and documenting through sub-agents.
2
+ description: Feature Factory — native stage orchestrator for planning, building, code review, documentation, and full review through sub-agents.
3
3
  mode: primary
4
4
  color: '#0fc24e'
5
- model: openai/gpt-5.5-fast
5
+ model: openai/gpt-5.3-codex-spark
6
6
  permissions:
7
7
  write: deny
8
8
  edit: deny
@@ -16,11 +16,10 @@ permissions:
16
16
  '*': allow
17
17
  task:
18
18
  building: allow
19
- reviewing: allow
19
+ code-review: allow
20
+ full-review: allow
20
21
  planning: allow
21
22
  documenting: allow
22
- explore: allow
23
- reasoningEffort: xhigh
24
23
  ---
25
24
 
26
25
  You are the Feature Factory workflow assistant. Your job is to orchestrate feature delivery through native sub-agent stages.
@@ -41,8 +40,11 @@ For any substantive user request, prefer sub-agent execution over direct handlin
41
40
 
42
41
  - `@planning`: clarify scope, risks, assumptions, and produce `FINAL_PLAN`. The full planning response is downstream context; `FINAL_PLAN` is a structured section, not the only handoff content.
43
42
  - `@building`: implement code changes, run commands/tests, and report results.
44
- - `@documenting`: update docs to match shipped behavior.
45
- - `@reviewing`: validate implementation and documentation gates.
43
+ - `@code-review`: perform first-pass implementation validation and return the code-review gate.
44
+ - `@documenting`: update docs to match shipped behavior after code-review approval.
45
+ - `@full-review`: validate implementation and documentation together for final gates.
46
+ - Do not use built-in `@explore`; route exploration-like investigation and validation work to `@code-review` or `@full-review`.
47
+ - Do not use built-in `@general`; route general implementation, maintenance, and rework to `@building`.
46
48
  - For external dependency or standards uncertainty, instruct stage agents to load the shared `ff-research-methods` skill.
47
49
 
48
50
  For every delegated stage, include an instruction to load `ff-oo` before any shell usage.
@@ -108,10 +110,12 @@ Use one fixed workflow only:
108
110
  1. Plan if no approved plan exists.
109
111
  2. Once scope is clear, summarize it in 1-3 bullets; for clear imperative requests, that summary records the scope and counts as authorization to proceed.
110
112
  3. Build.
111
- 4. Document.
112
- 5. Review (implementation and documentation gates).
113
- 6. If either review gate is not accepted, route back to Build.
114
- 7. Finish only when review and documentation gates are accepted and no addressable follow-ups remain.
113
+ 4. Code Review.
114
+ 5. If the code-review gate is not accepted, route back to Build with code-review feedback.
115
+ 6. Document after code-review approval.
116
+ 7. Full Review (combined implementation and documentation gates).
117
+ 8. If either full-review gate is not accepted, route back to Build.
118
+ 9. Finish only when code-review, full-review, and documentation gates are accepted and no addressable follow-ups remain.
115
119
 
116
120
  Do not perform isolation/worktree checks in this agent. Isolation and worktree policy are handled elsewhere.
117
121
 
@@ -158,7 +162,7 @@ CURRENT_STAGE_OBJECTIVE:
158
162
 
159
163
  Never pass unresolved placeholder aliases (for example unresolved result-alias syntax) in stage handoff prompts.
160
164
 
161
- `RAW_PREVIOUS_STAGE_OUTPUT` is the complete previous-stage last message by default. Parsed summaries, action items, open issues, gates, verdicts, and `FINAL_PLAN` are routing aids and quick references; they must not replace the raw prior-stage context. Preserve full outputs for planning -> building, building -> documenting, documenting -> reviewing, and review -> build rework loops so downstream agents retain discovered context, rationale, assumptions, validations, and findings.
165
+ `RAW_PREVIOUS_STAGE_OUTPUT` is the complete previous-stage last message by default. Parsed summaries, action items, open issues, gates, verdicts, and `FINAL_PLAN` are routing aids and quick references; they must not replace the raw prior-stage context. Preserve full outputs for planning -> building, building -> code-review, code-review -> building rework, code-review -> documenting, documenting -> full-review, and full-review -> build rework loops so downstream agents retain discovered context, rationale, assumptions, validations, and findings.
162
166
 
163
167
  Only truncate `RAW_PREVIOUS_STAGE_OUTPUT` when platform context limits make the full prior-stage output impossible to include. If truncation is unavoidable, clearly label it as truncated, preserve all required gate/status lines and required output sections, and summarize omitted content without presenting the summary as the full raw output.
164
168
 
@@ -201,16 +205,21 @@ When planning is approved, parse `PLANNING_GATE` and `FINAL_PLAN` for routing an
201
205
  For each iteration `n`:
202
206
 
203
207
  1. Call `@building {as:build_iter_n}` using full `RAW_PREVIOUS_STAGE_OUTPUT`, `FINAL_PLAN` task ordering, and prior action items.
204
- 2. Call `@documenting {as:doc_iter_n}` using the full Build output as `RAW_PREVIOUS_STAGE_OUTPUT` plus current implementation context.
205
- 3. Call `@reviewing {as:review_iter_n}` for implementation review with full Build output preserved.
206
- 4. Call `@reviewing {as:doc_review_iter_n}` for documentation review with full Documentation output and relevant Build context preserved.
207
- 5. Read gate lines exactly as:
208
+ 2. Call `@code-review {as:code_review_iter_n}` for implementation review with full Build output preserved.
209
+ 3. Read code-review gate lines exactly as:
210
+ - `CODE_REVIEW_GATE=APPROVED|REWORK|ESCALATE`
211
+ 4. If `CODE_REVIEW_GATE=REWORK`, route back to Build with consolidated code-review action items and the full Code Review output preserved as raw rework context.
212
+ 5. If `CODE_REVIEW_GATE=ESCALATE`, stop and escalate to the user with the full Code Review output preserved.
213
+ 6. If `CODE_REVIEW_GATE=APPROVED` but explicit addressable `OPEN_ISSUES`, `NON_BLOCKING_ISSUES`, action items, minor issues, or non-blocking follow-ups remain, route back to Build with consolidated code-review action items and the full Code Review output preserved as raw rework context.
214
+ 7. Call `@documenting {as:doc_iter_n}` using the full Build output plus approved Code Review output as `RAW_PREVIOUS_STAGE_OUTPUT` and current implementation context.
215
+ 8. Call `@full-review {as:full_review_iter_n}` for combined implementation and documentation review with full Documentation output and relevant Build and Code Review context preserved.
216
+ 9. Read full-review gate lines exactly as:
208
217
  - `REVIEW_GATE=APPROVED|REWORK|ESCALATE`
209
218
  - `DOCUMENTATION_GATE=APPROVED|REWORK|ESCALATE`
210
- 6. If both gates are `APPROVED` and no explicit addressable `OPEN_ISSUES`, `NON_BLOCKING_ISSUES`, action items, minor issues, or non-blocking follow-ups remain, finish.
211
- 7. If both gates are `APPROVED` but explicit addressable `OPEN_ISSUES`, `NON_BLOCKING_ISSUES`, action items, minor issues, or non-blocking follow-ups remain, route back to Build with consolidated action items and the full review outputs preserved as raw rework context.
212
- 8. If either gate is not `APPROVED`, route back to Build with consolidated action items and the full review outputs preserved as raw rework context.
213
- 9. If 10 iterations are exhausted, stop and escalate to the user.
219
+ 10. If both full-review gates are `APPROVED` and no explicit addressable `OPEN_ISSUES`, `NON_BLOCKING_ISSUES`, action items, minor issues, or non-blocking follow-ups remain, finish.
220
+ 11. If both full-review gates are `APPROVED` but explicit addressable `OPEN_ISSUES`, `NON_BLOCKING_ISSUES`, action items, minor issues, or non-blocking follow-ups remain, route back to Build with consolidated action items and the full Full Review output preserved as raw rework context.
221
+ 12. If either full-review gate is not `APPROVED`, route back to Build with consolidated action items and the full Full Review output preserved as raw rework context.
222
+ 13. If 10 iterations are exhausted, stop and escalate to the user.
214
223
 
215
224
  ### Autonomous continuation rule
216
225
 
@@ -218,13 +227,14 @@ For each iteration `n`:
218
227
  - Do not ask the user what to do next while required workflow stages remain unfinished.
219
228
  - Do not use optional phrasing like "If you want, I can..." for unfinished required workflow steps.
220
229
  - If a stage reports partial progress (for example "waiting for tests"), treat it as non-terminal and issue a focused same-stage follow-up immediately.
221
- - Treat approved review gates with explicit addressable `OPEN_ISSUES`, `NON_BLOCKING_ISSUES`, action items, minor issues, or non-blocking follow-ups as non-terminal; emit one deterministic Build rework continuation unless the issue is blocked, escalated, requires user input, or is not actionable.
230
+ - Treat approved code-review or full-review gates with explicit addressable `OPEN_ISSUES`, `NON_BLOCKING_ISSUES`, action items, minor issues, or non-blocking follow-ups as non-terminal; emit one deterministic Build rework continuation unless the issue is blocked, escalated, requires user input, or is not actionable.
222
231
 
223
232
  ### Fixed-workflow non-terminal invariant
224
233
 
225
- - After the required scope-clear authorization checkpoint, successful Build always proceeds to Document.
226
- - After the required scope-clear authorization checkpoint, successful Document always proceeds to Review.
227
- - Build and Document are stage-complete states, not workflow-complete states.
234
+ - After the required scope-clear authorization checkpoint, successful Build always proceeds to Code Review.
235
+ - After the required scope-clear authorization checkpoint, approved Code Review always proceeds to Document.
236
+ - After the required scope-clear authorization checkpoint, successful Document always proceeds to Full Review.
237
+ - Build, Code Review, and Document are stage-complete states, not workflow-complete states.
228
238
  - When deterministic continuation is required after scope-clear authorization, emit `RECOMMENDED_NEXT_STEP` exactly as defined in the Plugin continuation contract below.
229
239
 
230
240
  ### Direct-execution prohibition
@@ -273,14 +283,16 @@ Rules:
273
283
  - Emit `RECOMMENDED_NEXT_STEP` when the next workflow action is deterministic and does not require user input, including approved-but-addressable review follow-ups such as explicit `OPEN_ISSUES`, `NON_BLOCKING_ISSUES`, action items, minor issues, or non-blocking items.
274
284
  - Omit `RECOMMENDED_NEXT_STEP` when the workflow is fully complete, blocked, escalated, waiting on required user input, or has no addressable follow-up remaining.
275
285
  - Omit `RECOMMENDED_NEXT_STEP` when the recommendation is "None", "Nothing", "No further steps", or similar.
276
- - In the fixed workflow, successful Build continues to Document; successful Document continues to Review.
277
- - Successful Build and successful Document are stage-complete but not workflow-complete, so they normally require `RECOMMENDED_NEXT_STEP`.
278
- - For normal workflow progression, continue by delegating to stage agents directly (`@building`, `@documenting`, `@reviewing`), not by invoking slash commands such as `/ff-review`, `/ff-document`, or `/ff-rework`.
286
+ - In the fixed workflow, successful Build continues to Code Review; approved Code Review continues to Document; successful Document continues to Full Review.
287
+ - Successful Build, approved Code Review, and successful Document are stage-complete but not workflow-complete, so they normally require `RECOMMENDED_NEXT_STEP`.
288
+ - For normal workflow progression, continue by delegating to stage agents directly (`@building`, `@code-review`, `@documenting`, `@full-review`), not by invoking slash commands such as `/ff-review`, `/ff-document`, or `/ff-rework`.
279
289
 
280
290
  Examples:
281
291
 
282
- - Build succeeded -> `RECOMMENDED_NEXT_STEP` describes running Document.
283
- - Document succeeded -> `RECOMMENDED_NEXT_STEP` describes running Review.
284
- - Review requires changes -> `RECOMMENDED_NEXT_STEP` describes Build rework actions.
285
- - Review is approved but lists addressable minor or non-blocking issues -> `RECOMMENDED_NEXT_STEP` describes Build rework actions.
286
- - Review is approved with no open issues or only blocked/user-decision follow-ups -> omit `RECOMMENDED_NEXT_STEP`.
292
+ - Build succeeded -> `RECOMMENDED_NEXT_STEP` describes running Code Review.
293
+ - Code Review approved -> `RECOMMENDED_NEXT_STEP` describes running Document.
294
+ - Code Review requires changes -> `RECOMMENDED_NEXT_STEP` describes Build rework actions.
295
+ - Document succeeded -> `RECOMMENDED_NEXT_STEP` describes running Full Review.
296
+ - Full Review requires changes -> `RECOMMENDED_NEXT_STEP` describes Build rework actions.
297
+ - Full Review is approved but lists addressable minor or non-blocking issues -> `RECOMMENDED_NEXT_STEP` describes Build rework actions.
298
+ - Full Review is approved with no open issues or only blocked/user-decision follow-ups -> omit `RECOMMENDED_NEXT_STEP`.
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: Unified validation agent for code and documentation. Performs acceptance, quality, security, and architecture review with context-driven scope.
2
+ description: Full validation agent for code and documentation. Performs acceptance, quality, security, architecture, and documentation review with context-driven scope.
3
3
  mode: subagent
4
4
  color: '#8b5cf6'
5
5
  model: opencode/glm-5.1
@@ -15,7 +15,7 @@ tools:
15
15
  task: false
16
16
  ---
17
17
 
18
- You are the unified reviewing specialist.
18
+ You are the full-review specialist.
19
19
 
20
20
  ## Reasoning Depth
21
21
 
@@ -24,8 +24,8 @@ You are the unified reviewing specialist.
24
24
 
25
25
  ## Core Role
26
26
 
27
- - Validate implementation and documentation outputs.
28
- - Apply scope based on context: acceptance, code quality, security, architecture, documentation.
27
+ - Validate implementation and documentation outputs together after Build, Code Review, and Document stages have run.
28
+ - Apply scope based on context: acceptance, code quality, security, architecture, documentation, and workflow completeness.
29
29
  - Return actionable findings with severity and confidence.
30
30
 
31
31
  ## File Review Guidance
@@ -101,7 +101,7 @@ For external/library uncertainty needed to validate findings, load and follow `f
101
101
 
102
102
  ## Gate Contract
103
103
 
104
- When acting as gate reviewer, output status line exactly:
104
+ When acting as full-review gate reviewer, output status lines exactly:
105
105
 
106
106
  - `REVIEW_GATE=APPROVED|REWORK|ESCALATE`
107
107
  - `DOCUMENTATION_GATE=APPROVED|REWORK|ESCALATE`
@@ -109,9 +109,9 @@ When acting as gate reviewer, output status line exactly:
109
109
  ## Operating Mode
110
110
 
111
111
  - Use normalized, resolved handoff context (summary/status/action items/issues plus full resolved prior output by default) rather than file-based artifacts.
112
- - Treat `RAW_PREVIOUS_STAGE_OUTPUT` as the complete prior-stage last message unless it is explicitly labeled as truncated. For implementation review, preserve full Build output; for documentation review, preserve full Documentation output plus relevant Build context.
113
- - In review/rework loops, return findings with enough context for Build to receive the full review output, not only consolidated action bullets.
112
+ - Treat `RAW_PREVIOUS_STAGE_OUTPUT` as the complete prior-stage last message unless it is explicitly labeled as truncated. Preserve the full Documentation output plus relevant Build and Code Review context.
113
+ - In full-review→build rework loops, return findings with enough context for Build to receive the full review output, not only consolidated action bullets.
114
114
  - Never rely on unresolved placeholder aliases in handoff prompts.
115
115
  - Keep reports concise, evidence-based, and directly actionable for implementation follow-up.
116
- - Do not delegate to implementation stages from reviewing mode.
117
- - Never perform implementation or file-modifying work in reviewing mode.
116
+ - Do not delegate to implementation stages from full-review mode.
117
+ - Never perform implementation or file-modifying work in full-review mode.
@@ -3,6 +3,7 @@ description: Creates implementation plans and planning gates for pipeline and ad
3
3
  mode: subagent
4
4
  color: '#3b82f6'
5
5
  model: openai/gpt-5.5-fast
6
+ temperature: 0.2
6
7
  permissions:
7
8
  write: deny
8
9
  edit: deny
@@ -25,8 +26,6 @@ permissions:
25
26
  'gh *': allow
26
27
  'oo gh': allow
27
28
  'oo gh *': allow
28
- reasoningEffort: xhigh
29
- temperature: 0.2
30
29
  ---
31
30
 
32
31
  You are the planning specialist.
@@ -118,7 +117,7 @@ When producing plans, include:
118
117
 
119
118
  ## Delegation Guidance
120
119
 
121
- - Do not delegate to `@building`, `@reviewing`, `@documenting`, `@planning`, or `@explore`.
120
+ - Do not delegate to `@building`, `@code-review`, `@documenting`, `@full-review`, `@planning`, or `@explore`.
122
121
  - Never perform implementation or file-modifying work in planning mode.
123
122
 
124
123
  ## Gate Contract
package/bin/ff-deploy.js CHANGED
@@ -10,7 +10,7 @@
10
10
 
11
11
  import { promises as fs } from 'fs';
12
12
  import { join, dirname } from 'path';
13
- import { fileURLToPath } from 'url';
13
+ import { fileURLToPath, pathToFileURL } from 'url';
14
14
  import { homedir } from 'os';
15
15
 
16
16
  const __filename = fileURLToPath(import.meta.url);
@@ -29,8 +29,27 @@ const SOURCE_AGENTS_DIR = join(PACKAGE_ROOT, 'agents');
29
29
  const SOURCE_COMMANDS_DIR = join(PACKAGE_ROOT, 'commands');
30
30
  const SOURCE_AGENTS_GUIDE_FILE = join(PACKAGE_ROOT, 'AGENTS.md');
31
31
 
32
- // Check if running in interactive mode (has TTY)
32
+ // Only direct interactive CLI invocations are allowed to deploy assets or mutate
33
+ // the user's global OpenCode config. Non-interactive loads (for example plugin
34
+ // startup or MCP-server startup paths) must be no-ops.
33
35
  const isInteractive = process.stdin.isTTY && process.stdout.isTTY;
36
+ const invokedScript = process.argv[1];
37
+
38
+ async function isDirectInteractiveInvocation() {
39
+ if (!isInteractive || !invokedScript) {
40
+ return false;
41
+ }
42
+
43
+ try {
44
+ const [currentScriptPath, invokedScriptPath] = await Promise.all([
45
+ fs.realpath(__filename),
46
+ fs.realpath(invokedScript),
47
+ ]);
48
+ return currentScriptPath === invokedScriptPath;
49
+ } catch {
50
+ return import.meta.url === pathToFileURL(invokedScript).href;
51
+ }
52
+ }
34
53
 
35
54
  // Default MCP configuration
36
55
  const DEFAULT_MCP_SERVERS = {
@@ -54,6 +73,21 @@ const DEFAULT_PLUGINS = [
54
73
  'opencode-pty@latest',
55
74
  ];
56
75
 
76
+ const DEFAULT_DISABLED_AGENTS = {
77
+ build: { disable: true },
78
+ plan: { disable: true },
79
+ explore: { disable: true },
80
+ general: { disable: true },
81
+ };
82
+
83
+ const DEFAULT_PROVIDER_MODELS = {
84
+ openai: {
85
+ models: {
86
+ 'gpt-5.3-codex-spark': {},
87
+ },
88
+ },
89
+ };
90
+
57
91
  function getPackageBaseName(plugin) {
58
92
  if (plugin.startsWith('@')) {
59
93
  const slashIndex = plugin.indexOf('/');
@@ -79,6 +113,14 @@ function hasPlugin(existing, plugin) {
79
113
  return existing.some((entry) => getPackageBaseName(entry) === baseName);
80
114
  }
81
115
 
116
+ function isRecord(value) {
117
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
118
+ }
119
+
120
+ function hasOwn(record, key) {
121
+ return Object.prototype.hasOwnProperty.call(record, key);
122
+ }
123
+
82
124
  async function ensureDir(dir) {
83
125
  try {
84
126
  await fs.mkdir(dir, { recursive: true });
@@ -135,10 +177,10 @@ async function fileExists(filePath) {
135
177
  }
136
178
  }
137
179
 
138
- async function updateMCPConfig() {
180
+ async function updateOpenCodeConfig() {
139
181
  if (isInteractive) {
140
- console.log('\n🔧 MCP Configuration Update');
141
- console.log('============================\n');
182
+ console.log('\n🔧 OpenCode Configuration Update');
183
+ console.log('================================\n');
142
184
  }
143
185
 
144
186
  try {
@@ -170,14 +212,13 @@ async function updateMCPConfig() {
170
212
  }
171
213
  }
172
214
 
173
- // Check which MCP servers need to be added
174
- const existingMcp = existingConfig.mcp || {};
175
- const serversToAdd = {};
215
+ const existingMcp = isRecord(existingConfig.mcp) ? existingConfig.mcp : {};
216
+ const mergedMcp = { ...existingMcp };
176
217
  let serversAdded = 0;
177
218
  let serversSkipped = 0;
178
219
 
179
220
  for (const [serverName, serverConfig] of Object.entries(DEFAULT_MCP_SERVERS)) {
180
- if (existingMcp[serverName]) {
221
+ if (hasOwn(mergedMcp, serverName)) {
181
222
  // Server already exists, skip
182
223
  serversSkipped++;
183
224
  if (isInteractive) {
@@ -185,7 +226,7 @@ async function updateMCPConfig() {
185
226
  }
186
227
  } else {
187
228
  // Server doesn't exist, add it
188
- serversToAdd[serverName] = serverConfig;
229
+ mergedMcp[serverName] = serverConfig;
189
230
  serversAdded++;
190
231
  if (isInteractive) {
191
232
  console.log(` ✅ ${serverName}: will be added`);
@@ -193,27 +234,88 @@ async function updateMCPConfig() {
193
234
  }
194
235
  }
195
236
 
196
- const existingPlugins = Array.isArray(existingConfig.plugin)
197
- ? existingConfig.plugin.filter((entry) => typeof entry === 'string')
198
- : [];
199
- const pluginsToAdd = [];
237
+ const existingPlugins = Array.isArray(existingConfig.plugin) ? existingConfig.plugin : [];
238
+ const existingPluginNames = existingPlugins.filter((entry) => typeof entry === 'string');
239
+ const mergedPlugins = [...existingPlugins];
240
+ let pluginsAdded = 0;
241
+ let pluginsSkipped = 0;
200
242
 
201
243
  for (const plugin of DEFAULT_PLUGINS) {
202
- if (hasPlugin(existingPlugins, plugin)) {
244
+ if (hasPlugin(existingPluginNames, plugin)) {
245
+ pluginsSkipped++;
203
246
  if (isInteractive) {
204
247
  console.log(` ⏭️ ${plugin}: already exists, skipping`);
205
248
  }
206
249
  } else {
207
- pluginsToAdd.push(plugin);
250
+ mergedPlugins.push(plugin);
251
+ existingPluginNames.push(plugin);
252
+ pluginsAdded++;
208
253
  if (isInteractive) {
209
254
  console.log(` ✅ ${plugin}: will be added`);
210
255
  }
211
256
  }
212
257
  }
213
258
 
214
- if (serversAdded === 0 && pluginsToAdd.length === 0) {
259
+ const existingAgentConfig = isRecord(existingConfig.agent) ? existingConfig.agent : {};
260
+ const mergedAgentConfig = { ...existingAgentConfig };
261
+ let agentsAdded = 0;
262
+ let agentsSkipped = 0;
263
+
264
+ for (const [agentName, agentConfig] of Object.entries(DEFAULT_DISABLED_AGENTS)) {
265
+ if (hasOwn(mergedAgentConfig, agentName)) {
266
+ agentsSkipped++;
267
+ if (isInteractive) {
268
+ console.log(` ⏭️ ${agentName} agent: already exists, skipping`);
269
+ }
270
+ } else {
271
+ mergedAgentConfig[agentName] = agentConfig;
272
+ agentsAdded++;
273
+ if (isInteractive) {
274
+ console.log(` ✅ ${agentName} agent: will be disabled`);
275
+ }
276
+ }
277
+ }
278
+
279
+ const existingProvider = isRecord(existingConfig.provider) ? existingConfig.provider : {};
280
+ const existingOpenAI = isRecord(existingProvider.openai) ? existingProvider.openai : {};
281
+ const existingOpenAIModels = isRecord(existingOpenAI.models) ? existingOpenAI.models : {};
282
+ const mergedOpenAIModels = { ...existingOpenAIModels };
283
+ let providerModelsAdded = 0;
284
+ let providerModelsSkipped = 0;
285
+
286
+ for (const [modelName, modelConfig] of Object.entries(DEFAULT_PROVIDER_MODELS.openai.models)) {
287
+ if (hasOwn(mergedOpenAIModels, modelName)) {
288
+ providerModelsSkipped++;
289
+ if (isInteractive) {
290
+ console.log(` ⏭️ openai/${modelName}: already exists, skipping`);
291
+ }
292
+ } else {
293
+ mergedOpenAIModels[modelName] = modelConfig;
294
+ providerModelsAdded++;
295
+ if (isInteractive) {
296
+ console.log(` ✅ openai/${modelName}: will be added`);
297
+ }
298
+ }
299
+ }
300
+
301
+ const mergedProvider = {
302
+ ...existingProvider,
303
+ openai: {
304
+ ...existingOpenAI,
305
+ models: mergedOpenAIModels,
306
+ },
307
+ };
308
+
309
+ if (
310
+ serversAdded === 0 &&
311
+ pluginsAdded === 0 &&
312
+ agentsAdded === 0 &&
313
+ providerModelsAdded === 0
314
+ ) {
215
315
  if (isInteractive) {
216
- console.log('\n✅ Required MCP servers and plugins already configured. No changes needed.');
316
+ console.log(
317
+ '\n✅ Required OpenCode config defaults already configured. No changes needed.'
318
+ );
217
319
  }
218
320
  return;
219
321
  }
@@ -228,14 +330,13 @@ async function updateMCPConfig() {
228
330
  }
229
331
  }
230
332
 
231
- // Merge MCP config into existing config
333
+ // Merge global defaults into existing config without overwriting existing entries.
232
334
  const updatedConfig = {
233
335
  ...existingConfig,
234
- mcp: {
235
- ...existingMcp,
236
- ...serversToAdd,
237
- },
238
- plugin: [...existingPlugins, ...pluginsToAdd],
336
+ mcp: mergedMcp,
337
+ plugin: mergedPlugins,
338
+ agent: mergedAgentConfig,
339
+ provider: mergedProvider,
239
340
  };
240
341
 
241
342
  // Write updated config
@@ -245,21 +346,36 @@ async function updateMCPConfig() {
245
346
  if (isInteractive) {
246
347
  console.log(`\n✅ Updated OpenCode config: ${GLOBAL_CONFIG_FILE}`);
247
348
  console.log(` Added ${serversAdded} MCP server(s)`);
248
- console.log(` Added ${pluginsToAdd.length} plugin(s)`);
349
+ console.log(` Added ${pluginsAdded} plugin(s)`);
350
+ console.log(` Added ${agentsAdded} disabled agent config(s)`);
351
+ console.log(` Added ${providerModelsAdded} provider model(s)`);
249
352
  if (serversSkipped > 0) {
250
353
  console.log(` Skipped ${serversSkipped} existing server(s)`);
251
354
  }
355
+ if (pluginsSkipped > 0) {
356
+ console.log(` Skipped ${pluginsSkipped} existing plugin(s)`);
357
+ }
358
+ if (agentsSkipped > 0) {
359
+ console.log(` Skipped ${agentsSkipped} existing agent config(s)`);
360
+ }
361
+ if (providerModelsSkipped > 0) {
362
+ console.log(` Skipped ${providerModelsSkipped} existing provider model(s)`);
363
+ }
252
364
  console.log('\n📝 Note: Restart OpenCode to load new configuration');
253
365
  }
254
366
  } catch (error) {
255
367
  if (isInteractive) {
256
- console.error(`\n❌ Failed to update MCP config: ${error.message}`);
368
+ console.error(`\n❌ Failed to update OpenCode config: ${error.message}`);
257
369
  }
258
370
  throw error;
259
371
  }
260
372
  }
261
373
 
262
374
  async function deploy() {
375
+ if (!(await isDirectInteractiveInvocation())) {
376
+ return;
377
+ }
378
+
263
379
  if (isInteractive) {
264
380
  const pkgContent = await fs.readFile(join(PACKAGE_ROOT, 'package.json'), 'utf8');
265
381
  const pkgVersion = JSON.parse(pkgContent).version;
@@ -359,13 +475,14 @@ async function deploy() {
359
475
  console.log(' - Restart OpenCode or run /reload to load new agents and commands');
360
476
  console.log(' - Use @planning to create implementation plans');
361
477
  console.log(' - Use @building to execute plans');
362
- console.log(' - Use @reviewing to validate changes');
478
+ console.log(' - Use @code-review for first-pass code validation');
479
+ console.log(' - Use @full-review for combined code and documentation validation');
363
480
  console.log(' - Use /ff-review, /ff-document, or /ff-rework for quick subtask runs');
364
481
  console.log(' - Load ff-research-methods in stage agents for external research');
365
482
  }
366
483
 
367
- // Always update MCP config (no flag needed, no prompts)
368
- await updateMCPConfig();
484
+ // Explicit interactive deploy updates global OpenCode config (no prompts).
485
+ await updateOpenCodeConfig();
369
486
  } catch (error) {
370
487
  if (isInteractive) {
371
488
  console.error('\n❌ Deployment failed:', error.message);
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: Quick review helper (defaults to "Review the changes so far")
3
- agent: reviewing
3
+ agent: full-review
4
4
  subtask: false
5
5
  ---
6
6
 
@@ -1,11 +1,11 @@
1
- type BunShell = any;
2
1
  /**
3
2
  * Built-in opencode agents that should be disabled when the Feature Factory
4
3
  * plugin is active. These are the standard opencode agents that overlap with
5
- * the plugin's own agents (planning, building, reviewing).
4
+ * the plugin's own agents (planning, building, code-review, full-review) or should be routed
5
+ * through Feature Factory stage agents instead.
6
6
  *
7
- * Note: This only disables the built-in `build` and `plan` agents.
8
- * The plugin's own agents (planning, building, reviewing) remain active.
7
+ * Note: This disables built-in `build`, `plan`, `explore`, and `general` agents.
8
+ * The plugin's own agents (planning, building, code-review, full-review) remain active.
9
9
  */
10
10
  export declare const DEFAULT_DISABLED_AGENTS: Record<string, {
11
11
  disable: boolean;
@@ -23,16 +23,3 @@ export interface AgentConfigs {
23
23
  export declare function mergeAgentConfigs(existing: AgentConfigs | undefined, defaults: Record<string, {
24
24
  disable: boolean;
25
25
  }>): AgentConfigs;
26
- /**
27
- * Update the agent configuration in global opencode.json.
28
- *
29
- * This function:
30
- * 1. Reads existing config from ~/.config/opencode/opencode.json
31
- * 2. Preserves existing agent settings
32
- * 3. Adds default agent disabling for built-in agents that don't exist
33
- * 4. Writes updated config back to ~/.config/opencode/opencode.json
34
- *
35
- * @param $ - Bun shell instance
36
- */
37
- export declare function updateAgentConfig($: BunShell): Promise<void>;
38
- export {};
@@ -1,15 +1,17 @@
1
- import { isRecord, updateGlobalOpenCodeConfigBlock } from './opencode-global-config.js';
2
1
  /**
3
2
  * Built-in opencode agents that should be disabled when the Feature Factory
4
3
  * plugin is active. These are the standard opencode agents that overlap with
5
- * the plugin's own agents (planning, building, reviewing).
4
+ * the plugin's own agents (planning, building, code-review, full-review) or should be routed
5
+ * through Feature Factory stage agents instead.
6
6
  *
7
- * Note: This only disables the built-in `build` and `plan` agents.
8
- * The plugin's own agents (planning, building, reviewing) remain active.
7
+ * Note: This disables built-in `build`, `plan`, `explore`, and `general` agents.
8
+ * The plugin's own agents (planning, building, code-review, full-review) remain active.
9
9
  */
10
10
  export const DEFAULT_DISABLED_AGENTS = {
11
11
  build: { disable: true },
12
12
  plan: { disable: true },
13
+ explore: { disable: true },
14
+ general: { disable: true },
13
15
  };
14
16
  /**
15
17
  * Merge agent configs, preserving existing settings and adding new ones.
@@ -26,32 +28,3 @@ export function mergeAgentConfigs(existing, defaults) {
26
28
  }
27
29
  return result;
28
30
  }
29
- /**
30
- * Update the agent configuration in global opencode.json.
31
- *
32
- * This function:
33
- * 1. Reads existing config from ~/.config/opencode/opencode.json
34
- * 2. Preserves existing agent settings
35
- * 3. Adds default agent disabling for built-in agents that don't exist
36
- * 4. Writes updated config back to ~/.config/opencode/opencode.json
37
- *
38
- * @param $ - Bun shell instance
39
- */
40
- export async function updateAgentConfig($) {
41
- void $;
42
- await updateGlobalOpenCodeConfigBlock({
43
- blockName: 'agent',
44
- warningLabel: 'agent config',
45
- update: (existingBlock) => {
46
- const existingAgentConfigs = isRecord(existingBlock)
47
- ? existingBlock
48
- : undefined;
49
- const updatedAgentConfigs = mergeAgentConfigs(existingAgentConfigs, DEFAULT_DISABLED_AGENTS);
50
- const hasChanges = Object.keys(DEFAULT_DISABLED_AGENTS).some((agentName) => !existingAgentConfigs?.[agentName]);
51
- return {
52
- nextBlock: updatedAgentConfigs,
53
- changed: hasChanges,
54
- };
55
- },
56
- });
57
- }
package/dist/index.js CHANGED
@@ -1,9 +1,5 @@
1
1
  import { StopQualityGateHooksPlugin } from './stop-quality-gate.js';
2
2
  import { RecommendedNextStepHooksPlugin } from './auto-handoff.js';
3
- import { updateMCPConfig } from './mcp-config.js';
4
- import { updateAgentConfig } from './agent-config.js';
5
- import { updatePluginConfig } from './plugin-config.js';
6
- import { $ } from 'bun';
7
3
  function composeAsyncHandlers(...handlers) {
8
4
  const activeHandlers = handlers.filter((handler) => Boolean(handler));
9
5
  if (activeHandlers.length === 0) {
@@ -27,31 +23,6 @@ export const FeatureFactoryPlugin = async (input) => {
27
23
  if (!directory || directory === '' || directory === '/') {
28
24
  return {};
29
25
  }
30
- // Update MCP server configuration in global OpenCode config
31
- // This ensures Feature Factory MCP servers are available across projects
32
- try {
33
- await updateMCPConfig($);
34
- }
35
- catch {
36
- // Just log or ignore errors during config update to not break plugin load
37
- console.error('Failed to update MCP config in OpenCode plugin');
38
- }
39
- // Update agent configuration in global OpenCode config
40
- // This disables built-in agents that overlap with Feature Factory agents
41
- try {
42
- await updateAgentConfig($);
43
- }
44
- catch {
45
- console.error('Failed to update agent config in OpenCode plugin');
46
- }
47
- // Update plugin list in global OpenCode config
48
- // This ensures required companion plugins are present
49
- try {
50
- await updatePluginConfig($);
51
- }
52
- catch {
53
- console.error('Failed to update plugin config in OpenCode plugin');
54
- }
55
26
  // Load hooks from the quality gate plugin
56
27
  const qualityGateHooks = await StopQualityGateHooksPlugin(input).catch(() => ({}));
57
28
  const autoHandoffHooks = await RecommendedNextStepHooksPlugin(input).catch(() => ({}));
@@ -1,4 +1,3 @@
1
- type BunShell = any;
2
1
  /**
3
2
  * Default MCP server configuration to be added by the plugin
4
3
  * These servers will be merged into the global OpenCode config.
@@ -36,16 +35,3 @@ export interface MCPServers {
36
35
  * Existing servers take precedence (we never overwrite them).
37
36
  */
38
37
  export declare function mergeMCPServers(existing: MCPServers | undefined, defaults: typeof DEFAULT_MCP_SERVERS): MCPServers;
39
- /**
40
- * Update the MCP servers configuration in global opencode.json.
41
- *
42
- * This function:
43
- * 1. Reads existing config from ~/.config/opencode/opencode.json
44
- * 2. Preserves existing MCP servers
45
- * 3. Adds default Feature Factory MCP servers that don't exist
46
- * 4. Writes updated config back to ~/.config/opencode/opencode.json
47
- *
48
- * @param $ - Bun shell instance
49
- */
50
- export declare function updateMCPConfig($: BunShell): Promise<void>;
51
- export {};
@@ -1,4 +1,3 @@
1
- import { isRecord, updateGlobalOpenCodeConfigBlock } from './opencode-global-config.js';
2
1
  /**
3
2
  * Default MCP server configuration to be added by the plugin
4
3
  * These servers will be merged into the global OpenCode config.
@@ -35,32 +34,3 @@ export function mergeMCPServers(existing, defaults) {
35
34
  }
36
35
  return result;
37
36
  }
38
- /**
39
- * Update the MCP servers configuration in global opencode.json.
40
- *
41
- * This function:
42
- * 1. Reads existing config from ~/.config/opencode/opencode.json
43
- * 2. Preserves existing MCP servers
44
- * 3. Adds default Feature Factory MCP servers that don't exist
45
- * 4. Writes updated config back to ~/.config/opencode/opencode.json
46
- *
47
- * @param $ - Bun shell instance
48
- */
49
- export async function updateMCPConfig($) {
50
- void $;
51
- await updateGlobalOpenCodeConfigBlock({
52
- blockName: 'mcp',
53
- warningLabel: 'MCP config',
54
- update: (existingBlock) => {
55
- const existingMcpServers = isRecord(existingBlock)
56
- ? existingBlock
57
- : undefined;
58
- const updatedMcpServers = mergeMCPServers(existingMcpServers, DEFAULT_MCP_SERVERS);
59
- const hasChanges = Object.keys(DEFAULT_MCP_SERVERS).some((serverName) => !existingMcpServers?.[serverName]);
60
- return {
61
- nextBlock: updatedMcpServers,
62
- changed: hasChanges,
63
- };
64
- },
65
- });
66
- }
@@ -1,4 +1,3 @@
1
- type BunShell = any;
2
1
  /**
3
2
  * Default plugins that should be present in the global OpenCode config.
4
3
  * These will be merged into the existing plugin array without removing
@@ -33,17 +32,3 @@ export declare function hasPlugin(existing: string[], plugin: string): boolean;
33
32
  * being added.
34
33
  */
35
34
  export declare function mergePlugins(existing: string[] | undefined, defaults: readonly string[]): string[];
36
- /**
37
- * Update the plugin list in global opencode.json.
38
- *
39
- * This function:
40
- * 1. Reads existing config from ~/.config/opencode/opencode.json
41
- * 2. Preserves all existing plugins in the array
42
- * 3. Appends default Feature Factory plugins that aren't already present
43
- * (matched by base package name, so pinned versions are respected)
44
- * 4. Writes updated config back to ~/.config/opencode/opencode.json
45
- *
46
- * @param $ - Bun shell instance
47
- */
48
- export declare function updatePluginConfig($: BunShell): Promise<void>;
49
- export {};
@@ -1,4 +1,3 @@
1
- import { updateGlobalOpenCodeConfigBlock } from './opencode-global-config.js';
2
1
  /**
3
2
  * Default plugins that should be present in the global OpenCode config.
4
3
  * These will be merged into the existing plugin array without removing
@@ -69,33 +68,3 @@ export function mergePlugins(existing, defaults) {
69
68
  }
70
69
  return result;
71
70
  }
72
- /**
73
- * Update the plugin list in global opencode.json.
74
- *
75
- * This function:
76
- * 1. Reads existing config from ~/.config/opencode/opencode.json
77
- * 2. Preserves all existing plugins in the array
78
- * 3. Appends default Feature Factory plugins that aren't already present
79
- * (matched by base package name, so pinned versions are respected)
80
- * 4. Writes updated config back to ~/.config/opencode/opencode.json
81
- *
82
- * @param $ - Bun shell instance
83
- */
84
- export async function updatePluginConfig($) {
85
- void $;
86
- await updateGlobalOpenCodeConfigBlock({
87
- blockName: 'plugin',
88
- warningLabel: 'plugin config',
89
- update: (existingBlock) => {
90
- const existingPlugins = Array.isArray(existingBlock)
91
- ? existingBlock.filter((entry) => typeof entry === 'string')
92
- : undefined;
93
- const existingArray = existingPlugins ?? [];
94
- const hasChanges = DEFAULT_PLUGINS.some((plugin) => !hasPlugin(existingArray, plugin));
95
- return {
96
- nextBlock: mergePlugins(existingPlugins, DEFAULT_PLUGINS),
97
- changed: hasChanges,
98
- };
99
- },
100
- });
101
- }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "@syntesseraai/opencode-feature-factory",
4
- "version": "0.12.10",
4
+ "version": "0.13.0",
5
5
  "type": "module",
6
6
  "description": "OpenCode plugin for Feature Factory agents - provides sub-agents and skills for validation, review, security, and architecture assessment",
7
7
  "license": "MIT",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: ff-reviewing-architecture
3
- description: Architecture validation checklist for @reviewing using Well-Architected principles.
3
+ description: Architecture validation checklist for review agents using Well-Architected principles.
4
4
  license: MIT
5
5
  compatibility: opencode
6
6
  metadata:
@@ -10,7 +10,7 @@ metadata:
10
10
 
11
11
  # Reviewing Architecture Skill
12
12
 
13
- Use this skill when `@reviewing` evaluates architectural quality and system-level trade-offs.
13
+ Use this skill when `@code-review` or `@full-review` evaluates architectural quality and system-level trade-offs.
14
14
 
15
15
  ## Focus Areas
16
16
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: ff-reviewing-code-quality
3
- description: Code-quality review checklist for @reviewing. Use for correctness, maintainability, and test coverage validation.
3
+ description: Code-quality review checklist for review agents. Use for correctness, maintainability, and test coverage validation.
4
4
  license: MIT
5
5
  compatibility: opencode
6
6
  metadata:
@@ -10,7 +10,7 @@ metadata:
10
10
 
11
11
  # Reviewing Code Quality Skill
12
12
 
13
- Use this skill when `@reviewing` is validating implementation quality.
13
+ Use this skill when `@code-review` or `@full-review` is validating implementation quality.
14
14
 
15
15
  ## Focus Areas
16
16
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: ff-reviewing-documentation
3
- description: Documentation validation checklist for @reviewing. Use for accuracy, completeness, and repository consistency checks.
3
+ description: Documentation validation checklist for full-review agents. Use for accuracy, completeness, and repository consistency checks.
4
4
  license: MIT
5
5
  compatibility: opencode
6
6
  metadata:
@@ -10,7 +10,7 @@ metadata:
10
10
 
11
11
  # Reviewing Documentation Skill
12
12
 
13
- Use this skill when `@reviewing` validates documentation-stage outputs.
13
+ Use this skill when `@full-review` validates documentation-stage outputs.
14
14
 
15
15
  ## Focus Areas
16
16
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: ff-reviewing-security
3
- description: Security validation checklist for @reviewing. Use for auth, input handling, secret safety, and abuse-path review.
3
+ description: Security validation checklist for review agents. Use for auth, input handling, secret safety, and abuse-path review.
4
4
  license: MIT
5
5
  compatibility: opencode
6
6
  metadata:
@@ -10,7 +10,7 @@ metadata:
10
10
 
11
11
  # Reviewing Security Skill
12
12
 
13
- Use this skill when `@reviewing` performs security-focused validation.
13
+ Use this skill when `@code-review` or `@full-review` performs security-focused validation.
14
14
 
15
15
  ## Focus Areas
16
16
 
@@ -1,9 +0,0 @@
1
- export declare function isRecord(value: unknown): value is Record<string, unknown>;
2
- export declare function updateGlobalOpenCodeConfigBlock<T>(options: {
3
- blockName: string;
4
- warningLabel: string;
5
- update: (existingBlock: unknown) => {
6
- nextBlock: T;
7
- changed: boolean;
8
- };
9
- }): Promise<void>;
@@ -1,79 +0,0 @@
1
- import { mkdir, readFile, writeFile } from 'node:fs/promises';
2
- import { homedir } from 'node:os';
3
- import { join } from 'node:path';
4
- const GLOBAL_OPENCODE_DIR = join(homedir(), '.config', 'opencode');
5
- const GLOBAL_OPENCODE_CONFIG_PATH = join(GLOBAL_OPENCODE_DIR, 'opencode.json');
6
- export function isRecord(value) {
7
- return typeof value === 'object' && value !== null && !Array.isArray(value);
8
- }
9
- async function loadGlobalOpenCodeConfig() {
10
- try {
11
- const configContent = await readFile(GLOBAL_OPENCODE_CONFIG_PATH, 'utf8');
12
- const parsed = JSON.parse(configContent);
13
- if (!isRecord(parsed)) {
14
- return {
15
- config: {},
16
- hasExistingFile: true,
17
- parseError: true,
18
- };
19
- }
20
- return {
21
- config: parsed,
22
- hasExistingFile: true,
23
- parseError: false,
24
- };
25
- }
26
- catch (error) {
27
- if (typeof error === 'object' &&
28
- error !== null &&
29
- 'code' in error &&
30
- error.code === 'ENOENT') {
31
- return {
32
- config: {},
33
- hasExistingFile: false,
34
- parseError: false,
35
- };
36
- }
37
- if (error instanceof SyntaxError) {
38
- return {
39
- config: {},
40
- hasExistingFile: true,
41
- parseError: true,
42
- };
43
- }
44
- throw error;
45
- }
46
- }
47
- export async function updateGlobalOpenCodeConfigBlock(options) {
48
- const { blockName, warningLabel, update } = options;
49
- const loaded = await loadGlobalOpenCodeConfig();
50
- if (loaded.parseError) {
51
- console.warn(`[feature-factory] Could not update ${warningLabel}: existing opencode.json is not valid JSON`);
52
- return;
53
- }
54
- const { nextBlock, changed } = update(loaded.config[blockName]);
55
- if (!changed) {
56
- return;
57
- }
58
- const updatedConfig = {
59
- ...loaded.config,
60
- [blockName]: nextBlock,
61
- };
62
- await mkdir(GLOBAL_OPENCODE_DIR, { recursive: true });
63
- if (loaded.hasExistingFile && Object.keys(loaded.config).length > 0) {
64
- try {
65
- const timestamp = new Date().toISOString().split('T')[0].replace(/-/g, '');
66
- const backupPath = `${GLOBAL_OPENCODE_CONFIG_PATH}.backup.${timestamp}`;
67
- await writeFile(backupPath, JSON.stringify(loaded.config, null, 2));
68
- }
69
- catch (error) {
70
- console.warn('[feature-factory] Could not create backup:', error);
71
- }
72
- }
73
- try {
74
- await writeFile(GLOBAL_OPENCODE_CONFIG_PATH, JSON.stringify(updatedConfig, null, 2));
75
- }
76
- catch (error) {
77
- console.warn(`[feature-factory] Could not update ${warningLabel}:`, error);
78
- }
79
- }