@syntesseraai/opencode-feature-factory 0.6.4 → 0.6.6

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.
@@ -0,0 +1,16 @@
1
+ ---
2
+ description: Implement validated batches with Codex
3
+ subtask: true
4
+ agent: ff-building-codex
5
+ ---
6
+
7
+ Read `.feature-factory/agents/ff-building-gemini-batches-{UUID}.md` and implement tasks batch-by-batch.
8
+
9
+ For each task:
10
+
11
+ 1. implement code changes
12
+ 2. add/update tests
13
+ 3. run lint/typecheck/tests for impacted scope
14
+ 4. persist completion report to `.feature-factory/agents/ff-building-codex-{UUID}-T{N}.md`
15
+
16
+ This command performs implementation only; reviewing is triggered by `/pipeline/building/run` and by rework flow.
@@ -0,0 +1,19 @@
1
+ ---
2
+ description: Run build phase from approved plan
3
+ subtask: true
4
+ return:
5
+ - /pipeline/building/breakdown
6
+ - /pipeline/building/validate-batch
7
+ - /pipeline/building/implement-batch
8
+ - /pipeline/reviewing/run
9
+ ---
10
+
11
+ Run build phase from `.feature-factory/plans/plan-final-{UUID}.md`.
12
+
13
+ Rules:
14
+
15
+ 1. Maintain dependency-safe batching.
16
+ 2. Only parallelize tasks with no dependency edges.
17
+ 3. Persist batch/task outputs to `.feature-factory/agents/`.
18
+ 4. Implementation is Codex-only via `ff-building-codex` (model `openai/gpt-5.3-codex`).
19
+ 5. Send completed batches into reviewing via `/pipeline/reviewing/run`.
@@ -0,0 +1,16 @@
1
+ ---
2
+ description: Validate task batches for architecture and dependencies
3
+ subtask: true
4
+ agent: ff-building-gemini
5
+ ---
6
+
7
+ Read `.feature-factory/agents/ff-building-opus-tasks-{UUID}.md` and create dependency-safe batches.
8
+
9
+ For each batch:
10
+
11
+ 1. validate architecture and codebase fit
12
+ 2. confirm or adjust file targets
13
+ 3. flag architectural risks
14
+ 4. mark whether tasks can run in parallel
15
+
16
+ Persist enriched batches to `.feature-factory/agents/ff-building-gemini-batches-{UUID}.md`.
@@ -0,0 +1,12 @@
1
+ ---
2
+ description: Finalize pipeline run and summarize outcomes
3
+ subtask: true
4
+ model: openai/gpt-5.4
5
+ ---
6
+
7
+ Finalize the pipeline run.
8
+
9
+ 1. Summarize accepted plan, implemented tasks, review outcomes, and assumptions.
10
+ 2. Keep plans and reviews for auditability.
11
+ 3. Clear transient pipeline agent context files.
12
+ 4. Return concise completion report to user.
@@ -0,0 +1,22 @@
1
+ ---
2
+ description: Apply planning consensus gate
3
+ subtask: true
4
+ agent: ff-planning-codex
5
+ model: openai/gpt-5.4
6
+ ---
7
+
8
+ Read `.feature-factory/plans/plan-consensus-{UUID}.md` and apply the planning gate exactly:
9
+
10
+ - `>=75`: APPROVED
11
+ - `50-74`: REWORK
12
+ - `<50`: BLOCKED
13
+
14
+ Actions:
15
+
16
+ 1. If APPROVED, persist `.feature-factory/plans/plan-final-{UUID}.md` from the synthesized plan.
17
+ 2. If REWORK, append divergence feedback to pipeline context so the next planning loop iteration re-plans with explicit deltas.
18
+ 3. If BLOCKED, update pipeline context with explicit user-decision-needed status.
19
+
20
+ Always write a gate summary to pipeline context and include one status line in your final output:
21
+
22
+ `PLANNING_GATE=APPROVED|REWORK|BLOCKED`
@@ -0,0 +1,22 @@
1
+ ---
2
+ description: Generate Codex planning proposal
3
+ subtask: true
4
+ agent: ff-planning-codex
5
+ model: openai/gpt-5.3-codex
6
+ ---
7
+
8
+ Create a comprehensive implementation plan from the current pipeline requirements.
9
+
10
+ Requirements brief:
11
+
12
+ $ARGUMENTS
13
+
14
+ Persist plan content using `ff-plans-update` into `.feature-factory/plans/plan-codex-{UUID}.md`.
15
+
16
+ Include:
17
+
18
+ - requirements summary
19
+ - architecture validation for the proposed implementation approach
20
+ - ordered implementation steps with file targets
21
+ - risks and mitigations
22
+ - testing and validation strategy
@@ -0,0 +1,21 @@
1
+ ---
2
+ description: Generate Gemini planning proposal
3
+ subtask: true
4
+ agent: ff-planning-gemini
5
+ ---
6
+
7
+ Create a comprehensive implementation plan from the current pipeline requirements.
8
+
9
+ Requirements brief:
10
+
11
+ $ARGUMENTS
12
+
13
+ Persist plan content using `ff-plans-update` into `.feature-factory/plans/plan-gemini-{UUID}.md`.
14
+
15
+ Include:
16
+
17
+ - requirements summary
18
+ - architecture validation for the proposed implementation approach
19
+ - ordered implementation steps with file targets
20
+ - risks and mitigations
21
+ - testing and validation strategy
@@ -0,0 +1,21 @@
1
+ ---
2
+ description: Generate Opus planning proposal
3
+ subtask: true
4
+ agent: ff-planning-opus
5
+ ---
6
+
7
+ Create a comprehensive implementation plan from the current pipeline requirements.
8
+
9
+ Requirements brief:
10
+
11
+ $ARGUMENTS
12
+
13
+ Persist plan content using `ff-plans-update` into `.feature-factory/plans/plan-opus-{UUID}.md`.
14
+
15
+ Include:
16
+
17
+ - requirements summary
18
+ - architecture validation for the proposed implementation approach
19
+ - ordered implementation steps with file targets
20
+ - risks and mitigations
21
+ - testing and validation strategy
@@ -0,0 +1,25 @@
1
+ ---
2
+ description: Execute one planning iteration
3
+ subtask: true
4
+ model: openai/gpt-5.4
5
+ parallel:
6
+ - /pipeline/planning/run-opus {as:plan-opus}
7
+ - /pipeline/planning/run-gemini {as:plan-gemini}
8
+ - /pipeline/planning/run-codex {as:plan-codex}
9
+ return:
10
+ - /pipeline/planning/synthesize
11
+ - /pipeline/planning/gate
12
+ ---
13
+
14
+ Run one complete planning iteration for the active pipeline.
15
+
16
+ Requirements brief:
17
+
18
+ $ARGUMENTS
19
+
20
+ Rules:
21
+
22
+ 1. Persist each planner output to `.feature-factory/plans/plan-{model}-{UUID}.md`.
23
+ 2. Preserve prior planning artifacts for audit.
24
+ 3. Each planning model must include architecture validation in its proposal.
25
+ 4. Continue only through gate outcomes defined in `/pipeline/planning/gate`.
@@ -0,0 +1,18 @@
1
+ ---
2
+ description: Synthesize planning consensus
3
+ subtask: true
4
+ agent: ff-planning-codex
5
+ model: openai/gpt-5.4
6
+ ---
7
+
8
+ Read the latest planning artifacts (`plan-opus-{UUID}.md`, `plan-gemini-{UUID}.md`, `plan-codex-{UUID}.md`) and produce a consensus report.
9
+
10
+ Persist as `.feature-factory/plans/plan-consensus-{UUID}.md`.
11
+
12
+ Required output sections:
13
+
14
+ 1. `CONSENSUS_SCORE` (0-100)
15
+ 2. `AGREED_ELEMENTS`
16
+ 3. `DIVERGENT_ELEMENTS`
17
+ 4. `SYNTHESIZED_PLAN`
18
+ 5. `OPEN_QUESTIONS`
@@ -0,0 +1,16 @@
1
+ ---
2
+ description: Apply review approval gate
3
+ subtask: true
4
+ agent: ff-reviewing-codex
5
+ model: openai/gpt-5.4
6
+ ---
7
+
8
+ Read latest synthesis report and apply gate exactly:
9
+
10
+ - APPROVED when confidence `>=95` and unresolved issues count is `0`
11
+ - REWORK when below threshold and iteration < 10
12
+ - ESCALATE when iteration == 10 and still not approved
13
+
14
+ Persist gate decision in pipeline context and output one status line:
15
+
16
+ `REVIEW_GATE=APPROVED|REWORK|ESCALATE`
@@ -0,0 +1,12 @@
1
+ ---
2
+ description: Independent Codex review
3
+ subtask: true
4
+ agent: ff-reviewing-codex
5
+ model: openai/gpt-5.3-codex
6
+ ---
7
+
8
+ Review the current task from triage brief for correctness, quality, architecture validity, testing, security, and edge cases.
9
+
10
+ Classify findings as critical/high/medium/low and include confidence score.
11
+
12
+ Persist to `.feature-factory/agents/ff-reviewing-codex-{UUID}-T{N}.md`.
@@ -0,0 +1,11 @@
1
+ ---
2
+ description: Independent Gemini review
3
+ subtask: true
4
+ agent: ff-reviewing-gemini
5
+ ---
6
+
7
+ Review the current task from triage brief for correctness, quality, architecture validity, testing, security, and edge cases.
8
+
9
+ Classify findings as critical/high/medium/low and include confidence score.
10
+
11
+ Persist to `.feature-factory/agents/ff-reviewing-gemini-{UUID}-T{N}.md`.
@@ -0,0 +1,11 @@
1
+ ---
2
+ description: Independent Opus review
3
+ subtask: true
4
+ agent: ff-reviewing-opus
5
+ ---
6
+
7
+ Review the current task from triage brief for correctness, quality, architecture validity, testing, security, and edge cases.
8
+
9
+ Classify findings as critical/high/medium/low and include confidence score.
10
+
11
+ Persist to `.feature-factory/agents/ff-reviewing-opus-{UUID}-T{N}.md`.
@@ -0,0 +1,24 @@
1
+ ---
2
+ description: Run review loop for completed tasks
3
+ subtask: true
4
+ model: openai/gpt-5.4
5
+ loop:
6
+ max: 10
7
+ until: all tasks in the active batch are approved with confidence >=95 and zero unresolved issues
8
+ return:
9
+ - /pipeline/reviewing/triage
10
+ - /pipeline/reviewing/run-opus {as:review-opus}
11
+ - /pipeline/reviewing/run-gemini {as:review-gemini}
12
+ - /pipeline/reviewing/run-codex {as:review-codex}
13
+ - /pipeline/reviewing/synthesize
14
+ - /pipeline/reviewing/gate
15
+ - If `REVIEW_GATE=REWORK`, invoke `/pipeline/building/implement-batch` to apply fixes before the next loop iteration.
16
+ ---
17
+
18
+ Execute the review loop for the current completed tasks/rework report.
19
+
20
+ Stop criteria:
21
+
22
+ - approve when `>=95` confidence and zero unresolved issues
23
+ - continue loop while unresolved issues exist and iteration < 10
24
+ - escalate to user when iteration reaches 10 without approval
@@ -0,0 +1,18 @@
1
+ ---
2
+ description: Synthesize independent reviews into one report
3
+ subtask: true
4
+ agent: ff-reviewing-codex
5
+ model: openai/gpt-5.4
6
+ ---
7
+
8
+ Read the latest three review reports (Opus, Gemini, and Codex) and synthesize a single authoritative output.
9
+
10
+ Required output:
11
+
12
+ 1. overall confidence (0-100)
13
+ 2. consolidated deduplicated findings
14
+ 3. unresolved issues list
15
+ 4. verdict `APPROVED` or `REWORK_REQUIRED`
16
+ 5. explicit rework instructions when needed
17
+
18
+ Persist to `.feature-factory/agents/ff-reviewing-codex-synthesis-{UUID}-T{N}-iter{I}.md`.
@@ -0,0 +1,16 @@
1
+ ---
2
+ description: Build review brief from implementation outputs
3
+ subtask: true
4
+ agent: ff-reviewing-codex
5
+ model: openai/gpt-5.4
6
+ ---
7
+
8
+ Prepare a review brief for the current completed task or rework output.
9
+
10
+ Include:
11
+
12
+ - summary of implemented changes
13
+ - files changed
14
+ - focus areas and risk points
15
+
16
+ Persist to `.feature-factory/agents/ff-reviewing-codex-triage-{UUID}-T{N}.md`.
@@ -0,0 +1,21 @@
1
+ ---
2
+ description: Pipeline workflow entrypoint
3
+ subtask: true
4
+ model: openai/gpt-5.4
5
+ return:
6
+ - /pipeline/planning/run {loop:5 && until:planning gate is APPROVED or planning gate is BLOCKED and waiting for user confirmation}
7
+ - If planning is BLOCKED or loop max was reached, stop and ask the user whether to continue planning iterations. Otherwise continue.
8
+ - /pipeline/building/run
9
+ - /pipeline/complete
10
+ ---
11
+
12
+ Start the deterministic Feature Factory pipeline with this requirements brief:
13
+
14
+ $ARGUMENTS
15
+
16
+ Execution requirements:
17
+
18
+ 1. Create a pipeline UUID and persist orchestrator state in `.feature-factory/agents/pipeline-{UUID}.md` via `ff-agents-update`.
19
+ 2. Keep all phase artifacts in `.feature-factory/plans/` and `.feature-factory/reviews/`.
20
+ 3. Use command chaining, parallel fan-out, and loop gates from the `/pipeline/...` command tree.
21
+ 4. Do not skip planning and review gates.
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { StopQualityGateHooksPlugin } from './stop-quality-gate.js';
2
2
  import { updateMCPConfig } from './mcp-config.js';
3
3
  import { updateAgentConfig } from './agent-config.js';
4
+ import { updatePluginConfig } from './plugin-config.js';
4
5
  import { $ } from 'bun';
5
6
  // Import tool creator functions
6
7
  import { createFFAgentsCurrentTool } from './plugins/ff-agents-current-plugin.js';
@@ -53,6 +54,14 @@ export const FeatureFactoryPlugin = async (input) => {
53
54
  catch {
54
55
  console.error('Failed to update agent config in OpenCode plugin');
55
56
  }
57
+ // Update plugin list in global OpenCode config
58
+ // This ensures required companion plugins are present
59
+ try {
60
+ await updatePluginConfig($);
61
+ }
62
+ catch {
63
+ console.error('Failed to update plugin config in OpenCode plugin');
64
+ }
56
65
  // Load hooks from the quality gate plugin
57
66
  const qualityGateHooks = await StopQualityGateHooksPlugin(input).catch(() => ({}));
58
67
  // Create all tools
@@ -0,0 +1,49 @@
1
+ type BunShell = any;
2
+ /**
3
+ * Default plugins that should be present in the global OpenCode config.
4
+ * These will be merged into the existing plugin array without removing
5
+ * any user-added entries.
6
+ */
7
+ export declare const DEFAULT_PLUGINS: readonly string[];
8
+ /**
9
+ * Extract the base package name from a plugin specifier, stripping the
10
+ * version suffix. Handles both scoped (`@scope/name@version`) and
11
+ * unscoped (`name@version`) packages.
12
+ *
13
+ * Examples:
14
+ * "@scope/pkg@latest" → "@scope/pkg"
15
+ * "@scope/pkg@1.2.3" → "@scope/pkg"
16
+ * "pkg@latest" → "pkg"
17
+ * "pkg" → "pkg"
18
+ */
19
+ export declare function getPackageBaseName(plugin: string): string;
20
+ /**
21
+ * Check whether a plugin (by base name) is already present in the array,
22
+ * regardless of the version suffix. If a user has pinned a specific version
23
+ * (e.g. `@scope/pkg@1.2.3`), we treat the package as already present and
24
+ * do NOT add the `@latest` variant.
25
+ */
26
+ export declare function hasPlugin(existing: string[], plugin: string): boolean;
27
+ /**
28
+ * Merge plugin arrays, preserving existing entries and appending new ones.
29
+ * Existing entries are never removed or reordered.
30
+ *
31
+ * Matching is done by base package name (without version suffix), so a
32
+ * user-pinned `@scope/pkg@1.0.0` will prevent `@scope/pkg@latest` from
33
+ * being added.
34
+ */
35
+ 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 {};
@@ -0,0 +1,140 @@
1
+ import { readJsonFile } from './quality-gate-config.js';
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
+ /**
7
+ * Default plugins that should be present in the global OpenCode config.
8
+ * These will be merged into the existing plugin array without removing
9
+ * any user-added entries.
10
+ */
11
+ export const DEFAULT_PLUGINS = [
12
+ '@syntesseraai/opencode-feature-factory@latest',
13
+ '@nick-vi/opencode-type-inject@latest',
14
+ '@franlol/opencode-md-table-formatter@latest',
15
+ '@spoons-and-mirrors/subtask2@latest',
16
+ 'opencode-pty@latest',
17
+ '@angdrew/opencode-hashline-plugin@latest',
18
+ ];
19
+ /**
20
+ * Extract the base package name from a plugin specifier, stripping the
21
+ * version suffix. Handles both scoped (`@scope/name@version`) and
22
+ * unscoped (`name@version`) packages.
23
+ *
24
+ * Examples:
25
+ * "@scope/pkg@latest" → "@scope/pkg"
26
+ * "@scope/pkg@1.2.3" → "@scope/pkg"
27
+ * "pkg@latest" → "pkg"
28
+ * "pkg" → "pkg"
29
+ */
30
+ export function getPackageBaseName(plugin) {
31
+ if (plugin.startsWith('@')) {
32
+ // Scoped package: the version delimiter is the '@' after the '/'
33
+ const slashIndex = plugin.indexOf('/');
34
+ if (slashIndex !== -1) {
35
+ const versionAt = plugin.indexOf('@', slashIndex + 1);
36
+ if (versionAt !== -1) {
37
+ return plugin.substring(0, versionAt);
38
+ }
39
+ }
40
+ // No slash or no version suffix — return as-is
41
+ return plugin;
42
+ }
43
+ // Unscoped package: version delimiter is the first '@'
44
+ const atIndex = plugin.indexOf('@');
45
+ if (atIndex !== -1) {
46
+ return plugin.substring(0, atIndex);
47
+ }
48
+ return plugin;
49
+ }
50
+ /**
51
+ * Check whether a plugin (by base name) is already present in the array,
52
+ * regardless of the version suffix. If a user has pinned a specific version
53
+ * (e.g. `@scope/pkg@1.2.3`), we treat the package as already present and
54
+ * do NOT add the `@latest` variant.
55
+ */
56
+ export function hasPlugin(existing, plugin) {
57
+ const baseName = getPackageBaseName(plugin);
58
+ return existing.some((entry) => getPackageBaseName(entry) === baseName);
59
+ }
60
+ /**
61
+ * Merge plugin arrays, preserving existing entries and appending new ones.
62
+ * Existing entries are never removed or reordered.
63
+ *
64
+ * Matching is done by base package name (without version suffix), so a
65
+ * user-pinned `@scope/pkg@1.0.0` will prevent `@scope/pkg@latest` from
66
+ * being added.
67
+ */
68
+ export function mergePlugins(existing, defaults) {
69
+ const existingPlugins = existing ?? [];
70
+ const result = [...existingPlugins];
71
+ for (const plugin of defaults) {
72
+ if (!hasPlugin(result, plugin)) {
73
+ result.push(plugin);
74
+ }
75
+ }
76
+ return result;
77
+ }
78
+ /**
79
+ * Update the plugin list in global opencode.json.
80
+ *
81
+ * This function:
82
+ * 1. Reads existing config from ~/.config/opencode/opencode.json
83
+ * 2. Preserves all existing plugins in the array
84
+ * 3. Appends default Feature Factory plugins that aren't already present
85
+ * (matched by base package name, so pinned versions are respected)
86
+ * 4. Writes updated config back to ~/.config/opencode/opencode.json
87
+ *
88
+ * @param $ - Bun shell instance
89
+ */
90
+ export async function updatePluginConfig($) {
91
+ // Read existing global config
92
+ const globalJson = await readJsonFile($, GLOBAL_OPENCODE_CONFIG_PATH);
93
+ // Get existing plugins from global config
94
+ const existingPlugins = Array.isArray(globalJson?.plugin)
95
+ ? globalJson.plugin
96
+ : undefined;
97
+ // Check if any changes are needed (by base name)
98
+ const existingArray = existingPlugins ?? [];
99
+ const hasChanges = DEFAULT_PLUGINS.some((plugin) => !hasPlugin(existingArray, plugin));
100
+ if (!hasChanges) {
101
+ // All default plugins already present (possibly with pinned versions)
102
+ return;
103
+ }
104
+ // Merge with default plugins
105
+ const updatedPlugins = mergePlugins(existingPlugins, DEFAULT_PLUGINS);
106
+ // Prepare updated global config
107
+ const updatedGlobalConfig = {
108
+ ...(globalJson ?? {}),
109
+ plugin: updatedPlugins,
110
+ };
111
+ // Ensure global config directory exists
112
+ try {
113
+ await $ `mkdir -p ${GLOBAL_OPENCODE_DIR}`.quiet();
114
+ }
115
+ catch {
116
+ // Directory might already exist, ignore
117
+ }
118
+ // Backup existing global config if it exists and has content
119
+ if (globalJson && Object.keys(globalJson).length > 0) {
120
+ try {
121
+ const timestamp = new Date().toISOString().split('T')[0].replace(/-/g, '');
122
+ const backupPath = `${GLOBAL_OPENCODE_CONFIG_PATH}.backup.${timestamp}`;
123
+ const backupContent = JSON.stringify(globalJson, null, 2);
124
+ await $ `echo ${backupContent} > ${backupPath}`.quiet();
125
+ }
126
+ catch (error) {
127
+ // Backup failed, but continue anyway
128
+ console.warn('[feature-factory] Could not create backup:', error);
129
+ }
130
+ }
131
+ // Write updated config to global opencode.json
132
+ const configContent = JSON.stringify(updatedGlobalConfig, null, 2);
133
+ try {
134
+ await $ `echo ${configContent} > ${GLOBAL_OPENCODE_CONFIG_PATH}`.quiet();
135
+ }
136
+ catch (error) {
137
+ // Silently fail - don't block if we can't write the config
138
+ console.warn('[feature-factory] Could not update plugin config:', error);
139
+ }
140
+ }
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.6.4",
4
+ "version": "0.6.6",
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",
@@ -15,6 +15,7 @@
15
15
  "assets",
16
16
  "skills",
17
17
  "agents",
18
+ "commands",
18
19
  "bin"
19
20
  ],
20
21
  "keywords": [