devflow-kit 1.4.0 → 1.6.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/CHANGELOG.md +51 -0
- package/README.md +7 -3
- package/dist/commands/ambient.js +1 -1
- package/dist/commands/init.js +31 -2
- package/dist/commands/list.d.ts +21 -0
- package/dist/commands/list.js +71 -3
- package/dist/plugins.js +24 -24
- package/dist/utils/manifest.d.ts +45 -0
- package/dist/utils/manifest.js +100 -0
- package/dist/utils/post-install.js +6 -1
- package/package.json +1 -1
- package/plugins/devflow-accessibility/.claude-plugin/plugin.json +1 -1
- package/plugins/devflow-ambient/.claude-plugin/plugin.json +25 -4
- package/plugins/devflow-ambient/README.md +48 -29
- package/plugins/devflow-ambient/agents/coder.md +135 -0
- package/plugins/devflow-ambient/agents/reviewer.md +165 -0
- package/plugins/devflow-ambient/agents/scrutinizer.md +80 -0
- package/plugins/devflow-ambient/agents/shepherd.md +94 -0
- package/plugins/devflow-ambient/agents/simplifier.md +93 -0
- package/plugins/devflow-ambient/agents/skimmer.md +93 -0
- package/plugins/devflow-ambient/agents/validator.md +86 -0
- package/plugins/devflow-ambient/skills/ambient-router/SKILL.md +72 -28
- package/plugins/devflow-ambient/skills/ambient-router/references/skill-catalog.md +40 -34
- package/plugins/devflow-ambient/skills/debug-orchestration/SKILL.md +69 -0
- package/plugins/devflow-ambient/skills/implementation-orchestration/SKILL.md +92 -0
- package/plugins/devflow-ambient/skills/plan-orchestration/SKILL.md +71 -0
- package/plugins/devflow-audit-claude/.claude-plugin/plugin.json +10 -1
- package/plugins/devflow-audit-claude/commands/audit-claude.md +4 -0
- package/plugins/devflow-code-review/.claude-plugin/plugin.json +2 -1
- package/plugins/devflow-code-review/agents/reviewer.md +47 -9
- package/plugins/devflow-code-review/agents/synthesizer.md +12 -5
- package/plugins/devflow-code-review/commands/code-review-teams.md +43 -30
- package/plugins/devflow-code-review/commands/code-review.md +14 -2
- package/plugins/devflow-code-review/skills/knowledge-persistence/SKILL.md +128 -0
- package/plugins/devflow-code-review/skills/knowledge-persistence/references/examples.md +44 -0
- package/plugins/devflow-core-skills/.claude-plugin/plugin.json +2 -1
- package/plugins/devflow-core-skills/skills/docs-framework/SKILL.md +7 -1
- package/plugins/devflow-core-skills/skills/search-first/SKILL.md +133 -0
- package/plugins/devflow-core-skills/skills/search-first/references/evaluation-criteria.md +101 -0
- package/plugins/devflow-core-skills/skills/test-driven-development/SKILL.md +6 -5
- package/plugins/devflow-debug/.claude-plugin/plugin.json +5 -3
- package/plugins/devflow-debug/agents/synthesizer.md +211 -0
- package/plugins/devflow-debug/commands/debug-teams.md +28 -14
- package/plugins/devflow-debug/commands/debug.md +26 -12
- package/plugins/devflow-debug/skills/knowledge-persistence/SKILL.md +128 -0
- package/plugins/devflow-debug/skills/knowledge-persistence/references/examples.md +44 -0
- package/plugins/devflow-frontend-design/.claude-plugin/plugin.json +1 -1
- package/plugins/devflow-go/.claude-plugin/plugin.json +1 -1
- package/plugins/devflow-implement/.claude-plugin/plugin.json +2 -1
- package/plugins/devflow-implement/agents/coder.md +21 -13
- package/plugins/devflow-implement/agents/simplifier.md +32 -1
- package/plugins/devflow-implement/agents/skimmer.md +5 -0
- package/plugins/devflow-implement/agents/synthesizer.md +12 -5
- package/plugins/devflow-implement/commands/implement-teams.md +73 -60
- package/plugins/devflow-implement/commands/implement.md +45 -40
- package/plugins/devflow-implement/skills/knowledge-persistence/SKILL.md +128 -0
- package/plugins/devflow-implement/skills/knowledge-persistence/references/examples.md +44 -0
- package/plugins/devflow-java/.claude-plugin/plugin.json +1 -1
- package/plugins/devflow-python/.claude-plugin/plugin.json +1 -1
- package/plugins/devflow-react/.claude-plugin/plugin.json +1 -1
- package/plugins/devflow-resolve/.claude-plugin/plugin.json +4 -3
- package/plugins/devflow-resolve/agents/simplifier.md +32 -1
- package/plugins/devflow-resolve/commands/resolve-teams.md +16 -7
- package/plugins/devflow-resolve/commands/resolve.md +16 -7
- package/plugins/devflow-resolve/skills/knowledge-persistence/SKILL.md +128 -0
- package/plugins/devflow-resolve/skills/knowledge-persistence/references/examples.md +44 -0
- package/plugins/devflow-rust/.claude-plugin/plugin.json +1 -1
- package/plugins/devflow-self-review/.claude-plugin/plugin.json +10 -1
- package/plugins/devflow-self-review/agents/simplifier.md +32 -1
- package/plugins/devflow-self-review/commands/self-review.md +10 -4
- package/plugins/devflow-specify/.claude-plugin/plugin.json +1 -1
- package/plugins/devflow-specify/agents/skimmer.md +5 -0
- package/plugins/devflow-specify/agents/synthesizer.md +12 -5
- package/plugins/devflow-specify/commands/specify-teams.md +27 -20
- package/plugins/devflow-specify/commands/specify.md +26 -19
- package/plugins/devflow-typescript/.claude-plugin/plugin.json +1 -1
- package/scripts/hooks/ambient-prompt +8 -7
- package/scripts/hooks/session-start-memory +33 -3
- package/shared/agents/coder.md +21 -13
- package/shared/agents/reviewer.md +47 -9
- package/shared/agents/simplifier.md +32 -1
- package/shared/agents/skimmer.md +5 -0
- package/shared/agents/synthesizer.md +12 -5
- package/shared/skills/ambient-router/SKILL.md +72 -28
- package/shared/skills/ambient-router/references/skill-catalog.md +40 -34
- package/shared/skills/debug-orchestration/SKILL.md +69 -0
- package/shared/skills/docs-framework/SKILL.md +7 -1
- package/shared/skills/implementation-orchestration/SKILL.md +92 -0
- package/shared/skills/knowledge-persistence/SKILL.md +128 -0
- package/shared/skills/knowledge-persistence/references/examples.md +44 -0
- package/shared/skills/plan-orchestration/SKILL.md +71 -0
- package/shared/skills/search-first/SKILL.md +133 -0
- package/shared/skills/search-first/references/evaluation-criteria.md +101 -0
- package/shared/skills/test-driven-development/SKILL.md +6 -5
- package/plugins/devflow-ambient/commands/ambient.md +0 -110
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,54 @@ All notable changes to DevFlow will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.6.0] - 2026-03-19
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **Ambient agent orchestration**: ORCHESTRATED tier spawns agent pipelines for IMPLEMENT, DEBUG, PLAN intents
|
|
12
|
+
- **Orchestration skills**: `implementation-orchestration`, `debug-orchestration`, `plan-orchestration` for ambient agent pipelines
|
|
13
|
+
- **`knowledge-persistence` skill** (#145) — extraction procedure, lock protocol, loading instructions for project knowledge
|
|
14
|
+
- **Knowledge loading phase** (#145) — `/debug`, `/specify`, `/self-review` now load project knowledge at startup
|
|
15
|
+
- **Pitfall recording phase** (#145) — `/code-review`, `/resolve` record pitfalls to `.memory/knowledge/pitfalls.md`
|
|
16
|
+
- **Knowledge directory** (#145) — `.memory/knowledge/` with `decisions.md` (ADR-NNN, append-only) and `pitfalls.md` (area-specific gotchas)
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
- **Ambient mode**: Three depth tiers (QUICK/GUIDED/ORCHESTRATED) replacing old QUICK/GUIDED/ELEVATE
|
|
20
|
+
- **Ambient mode**: GUIDED tier for small-scope IMPLEMENT (≤2 files), simple DEBUG, focused PLAN, and REVIEW — main session with skills + Simplifier
|
|
21
|
+
- **Ambient mode**: BUILD intent renamed to IMPLEMENT for clarity
|
|
22
|
+
- **Coder agent**: Added `test-driven-development` and `search-first` to permanent skills
|
|
23
|
+
- **Command phase numbering** (#145) — renumbered fractional phases to sequential integers across 12 command files
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
- **Agent metadata** (#146) — fixed `subagent_type` in debug, added missing YAML frontmatter
|
|
27
|
+
- **Plugin count** (#146) — corrected to "8 core + 9 optional"
|
|
28
|
+
- **Skills catalog** (#146) — cataloged 3 missing skills in reference
|
|
29
|
+
- **Debug command** (#147) — removed non-standard `name=` parameter
|
|
30
|
+
- **Plugin descriptions** (#147, #148) — synced across plugin.json, plugins.ts, marketplace.json
|
|
31
|
+
- **Simplifier agent** (#148) — added Output/Boundaries sections
|
|
32
|
+
- **Plugin metadata** (#148) — added homepage/repository/license/keywords to 3 plugins
|
|
33
|
+
|
|
34
|
+
### Removed
|
|
35
|
+
- **`/ambient` command**: Ambient mode is now hook-only. Use `devflow ambient --enable` to activate.
|
|
36
|
+
|
|
37
|
+
### Behavioral Changes
|
|
38
|
+
- EXPLORE intent now always classifies as QUICK (was split QUICK/GUIDED)
|
|
39
|
+
- Simple text edits ("Update the README") classify as QUICK (was BUILD/GUIDED)
|
|
40
|
+
- Debug agent budget cap removed — agents scale to investigation needs
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## [1.5.0] - 2026-03-13
|
|
45
|
+
|
|
46
|
+
### Added
|
|
47
|
+
- **Search-first skill** (#111) — New skill enforcing research before building custom utility code. 4-phase loop: Need Analysis → Search (via Explore subagent) → Evaluate → Decide (Adopt/Extend/Compose/Build)
|
|
48
|
+
- **Reviewer confidence thresholds** (#113) — Each review finding now includes a visible confidence score (0-100%). Only ≥80% findings appear in main sections; lower-confidence items go to a capped Suggestions section. Adds consolidation rules to group similar issues and skip stylistic preferences
|
|
49
|
+
- **Version manifest** (#91) — Tracks installed version, plugins, and features in `manifest.json`. Enables upgrade detection during `devflow init` and shows install status in `devflow list`
|
|
50
|
+
|
|
51
|
+
### Fixed
|
|
52
|
+
- **Synthesizer review glob** — Fixed `${REVIEW_BASE_DIR}/*-report.*.md` glob that matched zero reviewer files; now uses `${REVIEW_BASE_DIR}/*.md` with self-exclusion
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
8
56
|
## [1.4.0] - 2026-03-09
|
|
9
57
|
|
|
10
58
|
### Added
|
|
@@ -853,6 +901,9 @@ devflow init
|
|
|
853
901
|
|
|
854
902
|
---
|
|
855
903
|
|
|
904
|
+
[Unreleased]: https://github.com/dean0x/devflow/compare/v1.4.0...HEAD
|
|
905
|
+
[1.6.0]: https://github.com/dean0x/devflow/compare/v1.5.0...v1.6.0
|
|
906
|
+
[1.5.0]: https://github.com/dean0x/devflow/compare/v1.4.0...v1.5.0
|
|
856
907
|
[1.4.0]: https://github.com/dean0x/devflow/compare/v1.3.3...v1.4.0
|
|
857
908
|
[1.3.3]: https://github.com/dean0x/devflow/compare/v1.3.2...v1.3.3
|
|
858
909
|
[1.3.2]: https://github.com/dean0x/devflow/compare/v1.3.1...v1.3.2
|
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ DevFlow adds structured commands that handle the full lifecycle: specify feature
|
|
|
24
24
|
- **Full-lifecycle implementation** — spec, explore, plan, code, validate, refine in one command
|
|
25
25
|
- **Automatic session memory** — survives restarts, `/clear`, and context compaction
|
|
26
26
|
- **Parallel debugging** — competing hypotheses investigated simultaneously
|
|
27
|
-
- **
|
|
27
|
+
- **35 quality skills** — 9 auto-activating core, 8 optional language/ecosystem, plus specialized review, agent, and orchestration skills
|
|
28
28
|
|
|
29
29
|
## Quick Start
|
|
30
30
|
|
|
@@ -48,7 +48,7 @@ Then in Claude Code:
|
|
|
48
48
|
| `devflow-resolve` | `/resolve` | Process review issues — fix or defer to tech debt |
|
|
49
49
|
| `devflow-debug` | `/debug` | Parallel hypothesis debugging |
|
|
50
50
|
| `devflow-self-review` | `/self-review` | Self-review workflow (Simplifier + Scrutinizer) |
|
|
51
|
-
| `devflow-ambient` |
|
|
51
|
+
| `devflow-ambient` | (hook) | Ambient mode — intent classification with agent orchestration |
|
|
52
52
|
| `devflow-core-skills` | (auto) | Auto-activating quality enforcement skills |
|
|
53
53
|
|
|
54
54
|
## Command Details
|
|
@@ -120,6 +120,7 @@ The `devflow-core-skills` plugin provides quality enforcement skills that activa
|
|
|
120
120
|
| `test-driven-development` | Implementing new features (RED-GREEN-REFACTOR) |
|
|
121
121
|
| `test-patterns` | Writing or modifying tests |
|
|
122
122
|
| `input-validation` | Creating API endpoints |
|
|
123
|
+
| `search-first` | Adding utilities, helpers, or infrastructure code |
|
|
123
124
|
|
|
124
125
|
## Language & Ecosystem Plugins
|
|
125
126
|
|
|
@@ -197,7 +198,10 @@ DevFlow creates project documentation in `.docs/` and working memory in `.memory
|
|
|
197
198
|
.memory/
|
|
198
199
|
├── WORKING-MEMORY.md # Auto-maintained by Stop hook
|
|
199
200
|
├── PROJECT-PATTERNS.md # Accumulated patterns across sessions
|
|
200
|
-
|
|
201
|
+
├── backup.json # Pre-compact git state snapshot
|
|
202
|
+
└── knowledge/
|
|
203
|
+
├── decisions.md # Architectural decisions (ADR-NNN, append-only)
|
|
204
|
+
└── pitfalls.md # Known pitfalls (area-specific gotchas)
|
|
201
205
|
```
|
|
202
206
|
|
|
203
207
|
## Workflow Examples
|
package/dist/commands/ambient.js
CHANGED
|
@@ -122,7 +122,7 @@ export const ambientCommand = new Command('ambient')
|
|
|
122
122
|
}
|
|
123
123
|
await fs.writeFile(settingsPath, updated, 'utf-8');
|
|
124
124
|
p.log.success('Ambient mode enabled — UserPromptSubmit hook registered');
|
|
125
|
-
p.log.info(color.dim('
|
|
125
|
+
p.log.info(color.dim('Skills auto-load and agents orchestrate based on each prompt'));
|
|
126
126
|
}
|
|
127
127
|
if (options.disable) {
|
|
128
128
|
const updated = removeAmbientHook(settingsContent);
|
package/dist/commands/init.js
CHANGED
|
@@ -15,6 +15,7 @@ import { detectPlatform, detectShell, getProfilePath, getSafeDeleteInfo, hasSafe
|
|
|
15
15
|
import { generateSafeDeleteBlock, installToProfile, removeFromProfile, getInstalledVersion, SAFE_DELETE_BLOCK_VERSION } from '../utils/safe-delete-install.js';
|
|
16
16
|
import { addAmbientHook } from './ambient.js';
|
|
17
17
|
import { addMemoryHooks, removeMemoryHooks } from './memory.js';
|
|
18
|
+
import { readManifest, writeManifest, resolvePluginList, detectUpgrade } from '../utils/manifest.js';
|
|
18
19
|
// Re-export pure functions for tests (canonical source is post-install.ts)
|
|
19
20
|
export { substituteSettingsTemplate, computeGitignoreAppend, applyTeamsConfig, stripTeamsConfig, mergeDenyList } from '../utils/post-install.js';
|
|
20
21
|
export { addAmbientHook, removeAmbientHook, hasAmbientHook } from './ambient.js';
|
|
@@ -61,7 +62,7 @@ export const initCommand = new Command('init')
|
|
|
61
62
|
.option('--plugin <names>', 'Install specific plugin(s), comma-separated (e.g., implement,code-review)')
|
|
62
63
|
.option('--teams', 'Enable Agent Teams (peer debate, adversarial review)')
|
|
63
64
|
.option('--no-teams', 'Disable Agent Teams (use parallel subagents instead)')
|
|
64
|
-
.option('--ambient', 'Enable ambient mode (
|
|
65
|
+
.option('--ambient', 'Enable ambient mode (classifies intent, loads skills, orchestrates agents)')
|
|
65
66
|
.option('--no-ambient', 'Disable ambient mode')
|
|
66
67
|
.option('--memory', 'Enable working memory (session context preservation)')
|
|
67
68
|
.option('--no-memory', 'Disable working memory hooks')
|
|
@@ -175,7 +176,7 @@ export const initCommand = new Command('init')
|
|
|
175
176
|
const ambientChoice = await p.select({
|
|
176
177
|
message: 'Enable ambient mode?',
|
|
177
178
|
options: [
|
|
178
|
-
{ value: true, label: 'Yes (Recommended)', hint: '
|
|
179
|
+
{ value: true, label: 'Yes (Recommended)', hint: 'Classifies intent, loads skills, orchestrates agents' },
|
|
179
180
|
{ value: false, label: 'No', hint: 'Full control — load skills manually' },
|
|
180
181
|
],
|
|
181
182
|
});
|
|
@@ -238,6 +239,17 @@ export const initCommand = new Command('init')
|
|
|
238
239
|
p.log.error(`Path configuration error: ${error instanceof Error ? error.message : error}`);
|
|
239
240
|
process.exit(1);
|
|
240
241
|
}
|
|
242
|
+
// Check existing manifest for upgrade detection
|
|
243
|
+
const existingManifest = await readManifest(devflowDir);
|
|
244
|
+
if (existingManifest) {
|
|
245
|
+
const upgrade = detectUpgrade(version, existingManifest.version);
|
|
246
|
+
if (upgrade.isUpgrade) {
|
|
247
|
+
s.message(`Upgrading from v${upgrade.previousVersion} to v${version}`);
|
|
248
|
+
}
|
|
249
|
+
else if (upgrade.isSameVersion) {
|
|
250
|
+
s.message('Reinstalling same version');
|
|
251
|
+
}
|
|
252
|
+
}
|
|
241
253
|
// Validate target directory
|
|
242
254
|
s.message('Validating target directory');
|
|
243
255
|
if (scope === 'local') {
|
|
@@ -519,6 +531,23 @@ export const initCommand = new Command('init')
|
|
|
519
531
|
p.log.info(`Deduplication: ${skillsMap.size} unique skills (from ${totalSkillDeclarations} declarations)`);
|
|
520
532
|
p.log.info(`Deduplication: ${agentsMap.size} unique agents (from ${totalAgentDeclarations} declarations)`);
|
|
521
533
|
}
|
|
534
|
+
// Write installation manifest for upgrade tracking (non-fatal — install already succeeded)
|
|
535
|
+
const installedPluginNames = pluginsToInstall.map(pl => pl.name);
|
|
536
|
+
const now = new Date().toISOString();
|
|
537
|
+
const manifestData = {
|
|
538
|
+
version,
|
|
539
|
+
plugins: resolvePluginList(installedPluginNames, existingManifest, !!options.plugin),
|
|
540
|
+
scope,
|
|
541
|
+
features: { teams: teamsEnabled, ambient: ambientEnabled, memory: memoryEnabled },
|
|
542
|
+
installedAt: existingManifest?.installedAt ?? now,
|
|
543
|
+
updatedAt: now,
|
|
544
|
+
};
|
|
545
|
+
try {
|
|
546
|
+
await writeManifest(devflowDir, manifestData);
|
|
547
|
+
}
|
|
548
|
+
catch (error) {
|
|
549
|
+
p.log.warn(`Failed to write installation manifest (install succeeded): ${error instanceof Error ? error.message : error}`);
|
|
550
|
+
}
|
|
522
551
|
p.outro(color.green('Ready! Run any command in Claude Code to get started.'));
|
|
523
552
|
});
|
|
524
553
|
//# sourceMappingURL=init.js.map
|
package/dist/commands/list.d.ts
CHANGED
|
@@ -1,3 +1,24 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
+
import { type ManifestData } from '../utils/manifest.js';
|
|
3
|
+
/**
|
|
4
|
+
* Format manifest feature flags into a human-readable comma-separated string.
|
|
5
|
+
* Returns 'none' when no features are enabled.
|
|
6
|
+
*/
|
|
7
|
+
export declare function formatFeatures(features: ManifestData['features']): string;
|
|
8
|
+
/**
|
|
9
|
+
* Determine effective installation scope based on which manifest was found.
|
|
10
|
+
* Local scope takes precedence when a local manifest exists.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveScope(localManifest: ManifestData | null): 'user' | 'local';
|
|
13
|
+
/**
|
|
14
|
+
* Compute the install status indicator for a plugin.
|
|
15
|
+
* Returns 'installed', 'not_installed', or 'unknown' (when no manifest exists).
|
|
16
|
+
*/
|
|
17
|
+
export declare function getPluginInstallStatus(pluginName: string, installedPlugins: ReadonlySet<string>, hasManifest: boolean): 'installed' | 'not_installed' | 'unknown';
|
|
18
|
+
/**
|
|
19
|
+
* Format the commands portion of a plugin entry.
|
|
20
|
+
* Returns the comma-separated command list or '(skills only)' for skill-only plugins.
|
|
21
|
+
*/
|
|
22
|
+
export declare function formatPluginCommands(commands: string[]): string;
|
|
2
23
|
export declare const listCommand: Command;
|
|
3
24
|
//# sourceMappingURL=list.d.ts.map
|
package/dist/commands/list.js
CHANGED
|
@@ -2,19 +2,87 @@ import { Command } from 'commander';
|
|
|
2
2
|
import * as p from '@clack/prompts';
|
|
3
3
|
import color from 'picocolors';
|
|
4
4
|
import { DEVFLOW_PLUGINS } from '../plugins.js';
|
|
5
|
+
import { getDevFlowDirectory } from '../utils/paths.js';
|
|
6
|
+
import { getGitRoot } from '../utils/git.js';
|
|
7
|
+
import { readManifest } from '../utils/manifest.js';
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
/**
|
|
10
|
+
* Format manifest feature flags into a human-readable comma-separated string.
|
|
11
|
+
* Returns 'none' when no features are enabled.
|
|
12
|
+
*/
|
|
13
|
+
export function formatFeatures(features) {
|
|
14
|
+
return [
|
|
15
|
+
features.teams ? 'teams' : null,
|
|
16
|
+
features.ambient ? 'ambient' : null,
|
|
17
|
+
features.memory ? 'memory' : null,
|
|
18
|
+
].filter(Boolean).join(', ') || 'none';
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Determine effective installation scope based on which manifest was found.
|
|
22
|
+
* Local scope takes precedence when a local manifest exists.
|
|
23
|
+
*/
|
|
24
|
+
export function resolveScope(localManifest) {
|
|
25
|
+
return localManifest ? 'local' : 'user';
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Compute the install status indicator for a plugin.
|
|
29
|
+
* Returns 'installed', 'not_installed', or 'unknown' (when no manifest exists).
|
|
30
|
+
*/
|
|
31
|
+
export function getPluginInstallStatus(pluginName, installedPlugins, hasManifest) {
|
|
32
|
+
if (!hasManifest)
|
|
33
|
+
return 'unknown';
|
|
34
|
+
return installedPlugins.has(pluginName) ? 'installed' : 'not_installed';
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Format the commands portion of a plugin entry.
|
|
38
|
+
* Returns the comma-separated command list or '(skills only)' for skill-only plugins.
|
|
39
|
+
*/
|
|
40
|
+
export function formatPluginCommands(commands) {
|
|
41
|
+
return commands.length > 0 ? commands.join(', ') : '(skills only)';
|
|
42
|
+
}
|
|
5
43
|
export const listCommand = new Command('list')
|
|
6
44
|
.description('List available DevFlow plugins')
|
|
7
|
-
.action(() => {
|
|
45
|
+
.action(async () => {
|
|
8
46
|
p.intro(color.bgCyan(color.black(' DevFlow Plugins ')));
|
|
47
|
+
// Resolve user manifest and git root in parallel (independent I/O)
|
|
48
|
+
const userDevflowDir = getDevFlowDirectory();
|
|
49
|
+
const [gitRoot, userManifest] = await Promise.all([
|
|
50
|
+
getGitRoot(),
|
|
51
|
+
readManifest(userDevflowDir),
|
|
52
|
+
]);
|
|
53
|
+
const localDevflowDir = gitRoot ? path.join(gitRoot, '.devflow') : null;
|
|
54
|
+
const localManifest = localDevflowDir ? await readManifest(localDevflowDir) : null;
|
|
55
|
+
const manifest = localManifest ?? userManifest;
|
|
56
|
+
// Show install status if manifest exists
|
|
57
|
+
if (manifest) {
|
|
58
|
+
const installedAt = new Date(manifest.installedAt).toLocaleDateString();
|
|
59
|
+
const updatedAt = new Date(manifest.updatedAt).toLocaleDateString();
|
|
60
|
+
const scope = resolveScope(localManifest);
|
|
61
|
+
const features = formatFeatures(manifest.features);
|
|
62
|
+
p.note(`${color.dim('Version:')} ${color.cyan(`v${manifest.version}`)}\n` +
|
|
63
|
+
`${color.dim('Scope:')} ${scope}\n` +
|
|
64
|
+
`${color.dim('Features:')} ${features}\n` +
|
|
65
|
+
`${color.dim('Installed:')} ${installedAt}` +
|
|
66
|
+
(installedAt !== updatedAt ? ` ${color.dim('Updated:')} ${updatedAt}` : ''), 'Installation');
|
|
67
|
+
}
|
|
68
|
+
const installedPlugins = new Set(manifest?.plugins ?? []);
|
|
69
|
+
const hasManifest = manifest !== null;
|
|
9
70
|
const maxNameLen = Math.max(...DEVFLOW_PLUGINS.map(p => p.name.length));
|
|
10
71
|
const pluginList = DEVFLOW_PLUGINS
|
|
11
72
|
.map(plugin => {
|
|
12
|
-
const cmds = plugin.commands
|
|
73
|
+
const cmds = formatPluginCommands(plugin.commands);
|
|
13
74
|
const optionalTag = plugin.optional ? color.dim(' (optional)') : '';
|
|
14
|
-
|
|
75
|
+
const status = getPluginInstallStatus(plugin.name, installedPlugins, hasManifest);
|
|
76
|
+
const installedTag = status === 'installed' ? color.green(' ✓')
|
|
77
|
+
: status === 'not_installed' ? color.dim(' ✗')
|
|
78
|
+
: '';
|
|
79
|
+
return `${color.cyan(plugin.name.padEnd(maxNameLen + 2))}${color.dim(plugin.description)}${optionalTag}${installedTag}\n${' '.repeat(maxNameLen + 2)}${color.yellow(cmds)}`;
|
|
15
80
|
})
|
|
16
81
|
.join('\n\n');
|
|
17
82
|
p.note(pluginList, 'Available plugins');
|
|
83
|
+
if (!manifest) {
|
|
84
|
+
p.log.info(color.dim('Run `devflow init` for install tracking'));
|
|
85
|
+
}
|
|
18
86
|
p.outro(color.dim('Install with: npx devflow-kit init --plugin=<name>'));
|
|
19
87
|
});
|
|
20
88
|
//# sourceMappingURL=list.js.map
|
package/dist/plugins.js
CHANGED
|
@@ -7,59 +7,59 @@
|
|
|
7
7
|
export const DEVFLOW_PLUGINS = [
|
|
8
8
|
{
|
|
9
9
|
name: 'devflow-core-skills',
|
|
10
|
-
description: 'Auto-activating quality enforcement
|
|
10
|
+
description: 'Auto-activating quality enforcement skills - foundation layer for all DevFlow plugins',
|
|
11
11
|
commands: [],
|
|
12
12
|
agents: [],
|
|
13
|
-
skills: ['core-patterns', 'docs-framework', 'git-safety', 'git-workflow', 'github-patterns', 'input-validation', 'test-driven-development', 'test-patterns'],
|
|
13
|
+
skills: ['core-patterns', 'docs-framework', 'git-safety', 'git-workflow', 'github-patterns', 'input-validation', 'search-first', 'test-driven-development', 'test-patterns'],
|
|
14
14
|
},
|
|
15
15
|
{
|
|
16
16
|
name: 'devflow-specify',
|
|
17
|
-
description: 'Interactive feature specification',
|
|
17
|
+
description: 'Interactive feature specification - creates well-defined GitHub issues',
|
|
18
18
|
commands: ['/specify'],
|
|
19
19
|
agents: ['skimmer', 'synthesizer'],
|
|
20
20
|
skills: ['agent-teams'],
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
23
|
name: 'devflow-implement',
|
|
24
|
-
description: 'Complete task implementation workflow',
|
|
24
|
+
description: 'Complete task implementation workflow with exploration, planning, and coding',
|
|
25
25
|
commands: ['/implement'],
|
|
26
26
|
agents: ['git', 'skimmer', 'synthesizer', 'coder', 'simplifier', 'scrutinizer', 'shepherd', 'validator'],
|
|
27
|
-
skills: ['agent-teams', 'implementation-patterns', 'self-review'],
|
|
27
|
+
skills: ['agent-teams', 'implementation-patterns', 'knowledge-persistence', 'self-review'],
|
|
28
28
|
},
|
|
29
29
|
{
|
|
30
30
|
name: 'devflow-code-review',
|
|
31
|
-
description: 'Comprehensive code review',
|
|
31
|
+
description: 'Comprehensive code review with parallel specialized agents',
|
|
32
32
|
commands: ['/code-review'],
|
|
33
33
|
agents: ['git', 'reviewer', 'synthesizer'],
|
|
34
|
-
skills: ['agent-teams', 'architecture-patterns', 'complexity-patterns', 'consistency-patterns', 'database-patterns', 'dependencies-patterns', 'documentation-patterns', 'performance-patterns', 'regression-patterns', 'review-methodology', 'security-patterns', 'test-patterns'],
|
|
34
|
+
skills: ['agent-teams', 'architecture-patterns', 'complexity-patterns', 'consistency-patterns', 'database-patterns', 'dependencies-patterns', 'documentation-patterns', 'knowledge-persistence', 'performance-patterns', 'regression-patterns', 'review-methodology', 'security-patterns', 'test-patterns'],
|
|
35
35
|
},
|
|
36
36
|
{
|
|
37
37
|
name: 'devflow-resolve',
|
|
38
|
-
description: 'Process and fix review issues',
|
|
38
|
+
description: 'Process and fix code review issues with risk assessment',
|
|
39
39
|
commands: ['/resolve'],
|
|
40
40
|
agents: ['git', 'resolver', 'simplifier'],
|
|
41
|
-
skills: ['agent-teams', 'implementation-patterns', 'security-patterns'],
|
|
41
|
+
skills: ['agent-teams', 'implementation-patterns', 'knowledge-persistence', 'security-patterns'],
|
|
42
42
|
},
|
|
43
43
|
{
|
|
44
44
|
name: 'devflow-debug',
|
|
45
|
-
description: 'Debugging with competing
|
|
45
|
+
description: 'Debugging workflows with competing hypothesis investigation using agent teams',
|
|
46
46
|
commands: ['/debug'],
|
|
47
|
-
agents: ['git'],
|
|
48
|
-
skills: ['agent-teams', 'git-safety'],
|
|
47
|
+
agents: ['git', 'synthesizer'],
|
|
48
|
+
skills: ['agent-teams', 'git-safety', 'knowledge-persistence'],
|
|
49
49
|
},
|
|
50
50
|
{
|
|
51
51
|
name: 'devflow-self-review',
|
|
52
|
-
description: 'Self-review workflow
|
|
52
|
+
description: 'Self-review workflow: Simplifier + Scrutinizer for code quality',
|
|
53
53
|
commands: ['/self-review'],
|
|
54
54
|
agents: ['simplifier', 'scrutinizer', 'validator'],
|
|
55
55
|
skills: ['self-review', 'core-patterns'],
|
|
56
56
|
},
|
|
57
57
|
{
|
|
58
58
|
name: 'devflow-ambient',
|
|
59
|
-
description: 'Ambient mode —
|
|
59
|
+
description: 'Ambient mode — intent classification with proportional agent orchestration',
|
|
60
60
|
commands: ['/ambient'],
|
|
61
|
-
agents: [],
|
|
62
|
-
skills: ['ambient-router'],
|
|
61
|
+
agents: ['coder', 'validator', 'simplifier', 'scrutinizer', 'shepherd', 'skimmer', 'reviewer'],
|
|
62
|
+
skills: ['ambient-router', 'implementation-orchestration', 'debug-orchestration', 'plan-orchestration'],
|
|
63
63
|
},
|
|
64
64
|
{
|
|
65
65
|
name: 'devflow-audit-claude',
|
|
@@ -71,7 +71,7 @@ export const DEVFLOW_PLUGINS = [
|
|
|
71
71
|
},
|
|
72
72
|
{
|
|
73
73
|
name: 'devflow-typescript',
|
|
74
|
-
description: 'TypeScript language patterns
|
|
74
|
+
description: 'TypeScript language patterns - type safety, generics, utility types, type guards',
|
|
75
75
|
commands: [],
|
|
76
76
|
agents: [],
|
|
77
77
|
skills: ['typescript'],
|
|
@@ -79,7 +79,7 @@ export const DEVFLOW_PLUGINS = [
|
|
|
79
79
|
},
|
|
80
80
|
{
|
|
81
81
|
name: 'devflow-react',
|
|
82
|
-
description: 'React framework patterns
|
|
82
|
+
description: 'React framework patterns - hooks, state management, composition, performance',
|
|
83
83
|
commands: [],
|
|
84
84
|
agents: [],
|
|
85
85
|
skills: ['react'],
|
|
@@ -87,7 +87,7 @@ export const DEVFLOW_PLUGINS = [
|
|
|
87
87
|
},
|
|
88
88
|
{
|
|
89
89
|
name: 'devflow-accessibility',
|
|
90
|
-
description: 'Web accessibility patterns
|
|
90
|
+
description: 'Web accessibility patterns - WCAG compliance, ARIA roles, keyboard navigation, focus management',
|
|
91
91
|
commands: [],
|
|
92
92
|
agents: [],
|
|
93
93
|
skills: ['accessibility'],
|
|
@@ -95,7 +95,7 @@ export const DEVFLOW_PLUGINS = [
|
|
|
95
95
|
},
|
|
96
96
|
{
|
|
97
97
|
name: 'devflow-frontend-design',
|
|
98
|
-
description: 'Frontend design patterns
|
|
98
|
+
description: 'Frontend design patterns - typography, color systems, spacing, motion, responsive design',
|
|
99
99
|
commands: [],
|
|
100
100
|
agents: [],
|
|
101
101
|
skills: ['frontend-design'],
|
|
@@ -103,7 +103,7 @@ export const DEVFLOW_PLUGINS = [
|
|
|
103
103
|
},
|
|
104
104
|
{
|
|
105
105
|
name: 'devflow-go',
|
|
106
|
-
description: 'Go language patterns
|
|
106
|
+
description: 'Go language patterns - error handling, interfaces, concurrency, package design',
|
|
107
107
|
commands: [],
|
|
108
108
|
agents: [],
|
|
109
109
|
skills: ['go'],
|
|
@@ -111,7 +111,7 @@ export const DEVFLOW_PLUGINS = [
|
|
|
111
111
|
},
|
|
112
112
|
{
|
|
113
113
|
name: 'devflow-java',
|
|
114
|
-
description: 'Java language patterns
|
|
114
|
+
description: 'Java language patterns - records, sealed classes, composition, modern Java features',
|
|
115
115
|
commands: [],
|
|
116
116
|
agents: [],
|
|
117
117
|
skills: ['java'],
|
|
@@ -119,7 +119,7 @@ export const DEVFLOW_PLUGINS = [
|
|
|
119
119
|
},
|
|
120
120
|
{
|
|
121
121
|
name: 'devflow-python',
|
|
122
|
-
description: 'Python language patterns
|
|
122
|
+
description: 'Python language patterns - type hints, protocols, dataclasses, async programming',
|
|
123
123
|
commands: [],
|
|
124
124
|
agents: [],
|
|
125
125
|
skills: ['python'],
|
|
@@ -127,7 +127,7 @@ export const DEVFLOW_PLUGINS = [
|
|
|
127
127
|
},
|
|
128
128
|
{
|
|
129
129
|
name: 'devflow-rust',
|
|
130
|
-
description: 'Rust language patterns
|
|
130
|
+
description: 'Rust language patterns - ownership, borrowing, error handling, type-driven design',
|
|
131
131
|
commands: [],
|
|
132
132
|
agents: [],
|
|
133
133
|
skills: ['rust'],
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Manifest data tracked for each DevFlow installation.
|
|
3
|
+
*/
|
|
4
|
+
export interface ManifestData {
|
|
5
|
+
version: string;
|
|
6
|
+
plugins: string[];
|
|
7
|
+
scope: 'user' | 'local';
|
|
8
|
+
features: {
|
|
9
|
+
teams: boolean;
|
|
10
|
+
ambient: boolean;
|
|
11
|
+
memory: boolean;
|
|
12
|
+
};
|
|
13
|
+
installedAt: string;
|
|
14
|
+
updatedAt: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Read and parse the manifest file. Returns null if missing or corrupt.
|
|
18
|
+
*/
|
|
19
|
+
export declare function readManifest(devflowDir: string): Promise<ManifestData | null>;
|
|
20
|
+
/**
|
|
21
|
+
* Write manifest to disk. Creates parent directory if needed.
|
|
22
|
+
*/
|
|
23
|
+
export declare function writeManifest(devflowDir: string, data: ManifestData): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Merge new plugins into existing plugin list (union, no duplicates).
|
|
26
|
+
* Preserves order: existing plugins first, then new ones appended.
|
|
27
|
+
*/
|
|
28
|
+
export declare function mergeManifestPlugins(existing: string[], newPlugins: string[]): string[];
|
|
29
|
+
/**
|
|
30
|
+
* Detect upgrade/downgrade/same version status.
|
|
31
|
+
*/
|
|
32
|
+
export interface UpgradeInfo {
|
|
33
|
+
isUpgrade: boolean;
|
|
34
|
+
isDowngrade: boolean;
|
|
35
|
+
isSameVersion: boolean;
|
|
36
|
+
previousVersion: string | null;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Resolve the final plugin list for a manifest write.
|
|
40
|
+
* On partial installs (--plugin flag), merge newly installed plugins into
|
|
41
|
+
* the existing manifest's plugin list. On full installs, replace entirely.
|
|
42
|
+
*/
|
|
43
|
+
export declare function resolvePluginList(installedPluginNames: string[], existingManifest: ManifestData | null, isPartialInstall: boolean): string[];
|
|
44
|
+
export declare function detectUpgrade(currentVersion: string, installedVersion: string | null): UpgradeInfo;
|
|
45
|
+
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { promises as fs } from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
/**
|
|
4
|
+
* Read and parse the manifest file. Returns null if missing or corrupt.
|
|
5
|
+
*/
|
|
6
|
+
export async function readManifest(devflowDir) {
|
|
7
|
+
const manifestPath = path.join(devflowDir, 'manifest.json');
|
|
8
|
+
try {
|
|
9
|
+
const content = await fs.readFile(manifestPath, 'utf-8');
|
|
10
|
+
const data = JSON.parse(content);
|
|
11
|
+
if (!data.version ||
|
|
12
|
+
!Array.isArray(data.plugins) ||
|
|
13
|
+
!data.scope ||
|
|
14
|
+
typeof data.features !== 'object' ||
|
|
15
|
+
data.features === null ||
|
|
16
|
+
typeof data.features.teams !== 'boolean' ||
|
|
17
|
+
typeof data.features.ambient !== 'boolean' ||
|
|
18
|
+
typeof data.features.memory !== 'boolean' ||
|
|
19
|
+
typeof data.installedAt !== 'string' ||
|
|
20
|
+
typeof data.updatedAt !== 'string') {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
return data;
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Write manifest to disk. Creates parent directory if needed.
|
|
31
|
+
*/
|
|
32
|
+
export async function writeManifest(devflowDir, data) {
|
|
33
|
+
await fs.mkdir(devflowDir, { recursive: true });
|
|
34
|
+
const manifestPath = path.join(devflowDir, 'manifest.json');
|
|
35
|
+
await fs.writeFile(manifestPath, JSON.stringify(data, null, 2) + '\n', 'utf-8');
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Merge new plugins into existing plugin list (union, no duplicates).
|
|
39
|
+
* Preserves order: existing plugins first, then new ones appended.
|
|
40
|
+
*/
|
|
41
|
+
export function mergeManifestPlugins(existing, newPlugins) {
|
|
42
|
+
const merged = [...existing];
|
|
43
|
+
for (const plugin of newPlugins) {
|
|
44
|
+
if (!merged.includes(plugin)) {
|
|
45
|
+
merged.push(plugin);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return merged;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Compare two semver strings. Returns -1, 0, or 1.
|
|
52
|
+
* Handles simple x.y.z versions; returns null for unparseable input.
|
|
53
|
+
*
|
|
54
|
+
* Note: Pre-release suffixes (e.g., `-beta.1`, `-rc.2`) are silently ignored.
|
|
55
|
+
* `1.0.0-beta.1` and `1.0.0` compare as equal. Build metadata is also ignored.
|
|
56
|
+
*/
|
|
57
|
+
function compareSemver(a, b) {
|
|
58
|
+
const parse = (v) => {
|
|
59
|
+
const match = v.match(/^v?(\d+)\.(\d+)\.(\d+)/);
|
|
60
|
+
return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : [];
|
|
61
|
+
};
|
|
62
|
+
const pa = parse(a);
|
|
63
|
+
const pb = parse(b);
|
|
64
|
+
if (pa.length === 0 || pb.length === 0)
|
|
65
|
+
return null;
|
|
66
|
+
for (let i = 0; i < 3; i++) {
|
|
67
|
+
if (pa[i] > pb[i])
|
|
68
|
+
return 1;
|
|
69
|
+
if (pa[i] < pb[i])
|
|
70
|
+
return -1;
|
|
71
|
+
}
|
|
72
|
+
return 0;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Resolve the final plugin list for a manifest write.
|
|
76
|
+
* On partial installs (--plugin flag), merge newly installed plugins into
|
|
77
|
+
* the existing manifest's plugin list. On full installs, replace entirely.
|
|
78
|
+
*/
|
|
79
|
+
export function resolvePluginList(installedPluginNames, existingManifest, isPartialInstall) {
|
|
80
|
+
if (existingManifest && isPartialInstall) {
|
|
81
|
+
return mergeManifestPlugins(existingManifest.plugins, installedPluginNames);
|
|
82
|
+
}
|
|
83
|
+
return installedPluginNames;
|
|
84
|
+
}
|
|
85
|
+
export function detectUpgrade(currentVersion, installedVersion) {
|
|
86
|
+
if (!installedVersion) {
|
|
87
|
+
return { isUpgrade: false, isDowngrade: false, isSameVersion: false, previousVersion: null };
|
|
88
|
+
}
|
|
89
|
+
const cmp = compareSemver(currentVersion, installedVersion);
|
|
90
|
+
if (cmp === null) {
|
|
91
|
+
return { isUpgrade: false, isDowngrade: false, isSameVersion: false, previousVersion: installedVersion };
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
isUpgrade: cmp > 0,
|
|
95
|
+
isDowngrade: cmp < 0,
|
|
96
|
+
isSameVersion: cmp === 0,
|
|
97
|
+
previousVersion: installedVersion,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -425,11 +425,16 @@ export async function createMemoryDir(verbose, cwd) {
|
|
|
425
425
|
const memoryDir = path.join(cwd ?? process.cwd(), '.memory');
|
|
426
426
|
try {
|
|
427
427
|
await fs.mkdir(memoryDir, { recursive: true });
|
|
428
|
+
await fs.mkdir(path.join(memoryDir, 'knowledge'), { recursive: true });
|
|
428
429
|
if (verbose) {
|
|
429
430
|
p.log.success('.memory/ directory ready');
|
|
430
431
|
}
|
|
431
432
|
}
|
|
432
|
-
catch {
|
|
433
|
+
catch (e) {
|
|
434
|
+
if (verbose) {
|
|
435
|
+
p.log.warn(`Failed to create .memory/ directory: ${e instanceof Error ? e.message : String(e)}`);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
433
438
|
}
|
|
434
439
|
/**
|
|
435
440
|
* Migrate memory files from .docs/ to .memory/.
|
package/package.json
CHANGED