wogiflow 2.5.7 → 2.5.8
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/.claude/settings.json +0 -1
- package/package.json +1 -1
- package/scripts/hooks/entry/claude-code/stop.js +86 -0
- package/.claude/rules/_internal/README.md +0 -64
- package/.claude/rules/_internal/document-structure.md +0 -77
- package/.claude/rules/_internal/dual-repo-management.md +0 -174
- package/.claude/rules/_internal/feature-refactoring-cleanup.md +0 -87
- package/.claude/rules/_internal/github-releases.md +0 -71
- package/.claude/rules/_internal/model-management.md +0 -35
- package/.claude/rules/_internal/self-maintenance.md +0 -87
- package/.claude/rules/architecture/component-reuse.md +0 -38
- package/.claude/rules/code-style/naming-conventions.md +0 -107
- package/.claude/rules/operations/git-workflows.md +0 -92
- package/.claude/rules/operations/scratch-directory.md +0 -54
- package/.claude/rules/security/security-patterns.md +0 -176
- package/.claude/skills/figma-analyzer/knowledge/learnings.md +0 -11
- package/.workflow/specs/architecture.md.template +0 -24
- package/.workflow/specs/stack.md.template +0 -33
- package/.workflow/specs/testing.md.template +0 -36
package/.claude/settings.json
CHANGED
package/package.json
CHANGED
|
@@ -61,6 +61,92 @@ runHook('Stop', async ({ parsedInput }) => {
|
|
|
61
61
|
};
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
// Workspace worker: auto-write results back to manager when stopping
|
|
65
|
+
// This runs in the hook (not the AI), so it's guaranteed to execute.
|
|
66
|
+
// The AI can't be relied on to call workspace_send_message — the stop
|
|
67
|
+
// hook fires before the AI gets a chance, or the AI forgets.
|
|
68
|
+
if (process.env.WOGI_WORKSPACE_ROOT && process.env.WOGI_REPO_NAME) {
|
|
69
|
+
try {
|
|
70
|
+
const fs = require('node:fs');
|
|
71
|
+
const path = require('node:path');
|
|
72
|
+
const crypto = require('node:crypto');
|
|
73
|
+
const workspaceRoot = process.env.WOGI_WORKSPACE_ROOT;
|
|
74
|
+
const repoName = process.env.WOGI_REPO_NAME;
|
|
75
|
+
const messagesDir = path.join(workspaceRoot, '.workspace', 'messages');
|
|
76
|
+
fs.mkdirSync(messagesDir, { recursive: true });
|
|
77
|
+
|
|
78
|
+
// Build summary from available state
|
|
79
|
+
const summary = [];
|
|
80
|
+
const { PATHS, safeJsonParse } = require('../../flow-utils');
|
|
81
|
+
|
|
82
|
+
// Get current/recently completed task info
|
|
83
|
+
const ready = safeJsonParse(path.join(PATHS.state, 'ready.json'), {});
|
|
84
|
+
const recentTask = (ready.recentlyCompleted || [])[0];
|
|
85
|
+
const inProgressTask = (ready.inProgress || [])[0];
|
|
86
|
+
const task = recentTask || inProgressTask;
|
|
87
|
+
|
|
88
|
+
if (task) {
|
|
89
|
+
summary.push(`**Task**: ${task.title || task.id}`);
|
|
90
|
+
if (task.type) summary.push(`**Type**: ${task.type}`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Get last request-log entry
|
|
94
|
+
try {
|
|
95
|
+
const logPath = path.join(PATHS.root, 'request-log.md');
|
|
96
|
+
if (fs.existsSync(logPath)) {
|
|
97
|
+
const stat = fs.statSync(logPath);
|
|
98
|
+
if (stat.size < 200 * 1024) {
|
|
99
|
+
const logContent = fs.readFileSync(logPath, 'utf-8');
|
|
100
|
+
const parts = logContent.split(/^### R-/m);
|
|
101
|
+
if (parts.length > 1) {
|
|
102
|
+
const lastEntry = parts[parts.length - 1];
|
|
103
|
+
if (lastEntry.length < 2000) {
|
|
104
|
+
summary.push(`**Log entry**:\n### R-${lastEntry.trim()}`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
} catch (_err) { /* non-critical */ }
|
|
110
|
+
|
|
111
|
+
// Get git status for changed files
|
|
112
|
+
try {
|
|
113
|
+
const { execSync } = require('node:child_process');
|
|
114
|
+
const diff = execSync('git diff --name-only HEAD 2>/dev/null || true', { cwd: PATHS.root, encoding: 'utf-8' }).trim();
|
|
115
|
+
const staged = execSync('git diff --name-only --staged 2>/dev/null || true', { cwd: PATHS.root, encoding: 'utf-8' }).trim();
|
|
116
|
+
const allChanged = [...new Set([...diff.split('\n'), ...staged.split('\n')].filter(Boolean))];
|
|
117
|
+
if (allChanged.length > 0) {
|
|
118
|
+
summary.push(`**Files changed**: ${allChanged.join(', ')}`);
|
|
119
|
+
}
|
|
120
|
+
} catch (_err) { /* non-critical */ }
|
|
121
|
+
|
|
122
|
+
const msgId = 'msg-' + crypto.randomBytes(4).toString('hex');
|
|
123
|
+
const message = {
|
|
124
|
+
id: msgId,
|
|
125
|
+
from: repoName,
|
|
126
|
+
to: 'manager',
|
|
127
|
+
type: 'task-complete',
|
|
128
|
+
priority: 'medium',
|
|
129
|
+
timestamp: new Date().toISOString(),
|
|
130
|
+
subject: task ? `Completed: ${task.title || task.id}` : `Work completed by ${repoName}`,
|
|
131
|
+
body: summary.join('\n') || `${repoName} finished processing.`,
|
|
132
|
+
taskId: task?.id || null,
|
|
133
|
+
actionRequired: false,
|
|
134
|
+
status: 'pending'
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
fs.writeFileSync(path.join(messagesDir, `${msgId}.json`), JSON.stringify(message, null, 2));
|
|
138
|
+
|
|
139
|
+
if (process.env.DEBUG) {
|
|
140
|
+
console.error(`[Stop] Workspace message written: ${msgId}`);
|
|
141
|
+
}
|
|
142
|
+
} catch (err) {
|
|
143
|
+
// Non-critical — best effort
|
|
144
|
+
if (process.env.DEBUG) {
|
|
145
|
+
console.error(`[Stop] Workspace message failed: ${err.message}`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
64
150
|
// Check if loop can exit
|
|
65
151
|
return await checkLoopExit();
|
|
66
152
|
}, { failMode: 'warn', failOutput: { continue: false } });
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
alwaysApply: false
|
|
3
|
-
description: "Meta-documentation about how project rules are organized"
|
|
4
|
-
---
|
|
5
|
-
# Project Rules
|
|
6
|
-
|
|
7
|
-
This directory contains coding rules and patterns for this project, organized by category.
|
|
8
|
-
|
|
9
|
-
## Structure
|
|
10
|
-
|
|
11
|
-
```
|
|
12
|
-
.claude/rules/
|
|
13
|
-
├── code-style/ # Naming conventions, formatting
|
|
14
|
-
│ └── naming-conventions.md
|
|
15
|
-
├── security/ # Security patterns and practices
|
|
16
|
-
│ └── security-patterns.md
|
|
17
|
-
├── architecture/ # Design decisions and patterns
|
|
18
|
-
│ ├── component-reuse.md
|
|
19
|
-
│ └── model-management.md
|
|
20
|
-
└── README.md
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
## How Rules Work
|
|
24
|
-
|
|
25
|
-
Rules are automatically loaded by Claude Code based on:
|
|
26
|
-
- **alwaysApply: true** - Rule is always loaded
|
|
27
|
-
- **alwaysApply: false** - Rule is loaded based on `globs` or `description` relevance
|
|
28
|
-
- **globs** - File patterns that trigger rule loading
|
|
29
|
-
|
|
30
|
-
## Adding New Rules
|
|
31
|
-
|
|
32
|
-
1. Choose the appropriate category subdirectory
|
|
33
|
-
2. Create a `.md` file with frontmatter:
|
|
34
|
-
|
|
35
|
-
```yaml
|
|
36
|
-
---
|
|
37
|
-
alwaysApply: false
|
|
38
|
-
description: "Brief description for relevance matching"
|
|
39
|
-
globs: src/**/*.ts # Optional: only load for these files
|
|
40
|
-
---
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
3. Write the rule content in markdown
|
|
44
|
-
|
|
45
|
-
## Categories
|
|
46
|
-
|
|
47
|
-
| Category | Purpose |
|
|
48
|
-
|----------|---------|
|
|
49
|
-
| code-style | Naming conventions, formatting, file structure |
|
|
50
|
-
| security | Security patterns, input validation, safe practices |
|
|
51
|
-
| architecture | Design decisions, component patterns, system organization |
|
|
52
|
-
|
|
53
|
-
## Auto-Generation
|
|
54
|
-
|
|
55
|
-
Some rules can be auto-generated from `.workflow/state/decisions.md`:
|
|
56
|
-
|
|
57
|
-
```bash
|
|
58
|
-
node scripts/flow-rules-sync.js
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
The sync script will route rules to appropriate category subdirectories.
|
|
62
|
-
|
|
63
|
-
---
|
|
64
|
-
Last updated: 2026-01-12
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
alwaysApply: false
|
|
3
|
-
description: "All AI-context documents must use PIN markers for targeted context loading"
|
|
4
|
-
globs: ".workflow/**/*.md"
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Document Structure for AI Context
|
|
8
|
-
|
|
9
|
-
All documents in `.workflow/` that are used as AI context MUST follow the PIN standard.
|
|
10
|
-
|
|
11
|
-
## Required Structure
|
|
12
|
-
|
|
13
|
-
### 1. Header with PIN List
|
|
14
|
-
Every document starts with a comment listing all pins in the document:
|
|
15
|
-
```markdown
|
|
16
|
-
<!-- PINS: pin1, pin2, pin3 -->
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
### 2. Section PIN Markers
|
|
20
|
-
Each major section has a PIN marker comment:
|
|
21
|
-
```markdown
|
|
22
|
-
### Section Title
|
|
23
|
-
<!-- PIN: section-specific-pin -->
|
|
24
|
-
[Content]
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
### 3. PIN Naming Convention
|
|
28
|
-
- Use kebab-case: `user-authentication`, not `userAuthentication`
|
|
29
|
-
- Use semantic names: `error-handling`, not `eh`
|
|
30
|
-
- Use compound names for specificity: `json-parse-safety`
|
|
31
|
-
|
|
32
|
-
## Why PINs Matter
|
|
33
|
-
|
|
34
|
-
The PIN system enables:
|
|
35
|
-
1. **Targeted context loading**: Only load sections relevant to current task
|
|
36
|
-
2. **Cheaper model routing**: Haiku can fetch only relevant sections for Opus
|
|
37
|
-
3. **Change detection**: Hash sections independently for smart invalidation
|
|
38
|
-
4. **Cross-reference**: Link sections by PIN across documents
|
|
39
|
-
|
|
40
|
-
## Example Document
|
|
41
|
-
|
|
42
|
-
```markdown
|
|
43
|
-
# Config Reference
|
|
44
|
-
|
|
45
|
-
<!-- PINS: database, authentication, api-keys, environment -->
|
|
46
|
-
|
|
47
|
-
## Database Settings
|
|
48
|
-
<!-- PIN: database -->
|
|
49
|
-
| Setting | Default | Description |
|
|
50
|
-
|---------|---------|-------------|
|
|
51
|
-
|
|
52
|
-
## Authentication
|
|
53
|
-
<!-- PIN: authentication -->
|
|
54
|
-
| Setting | Default | Description |
|
|
55
|
-
|---------|---------|-------------|
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
## Parsing
|
|
59
|
-
|
|
60
|
-
The PIN system automatically parses documents with:
|
|
61
|
-
- `flow-section-index.js` - Generates section index with pins
|
|
62
|
-
- `flow-section-resolver.js` - Resolves sections by PIN lookup
|
|
63
|
-
- `getSectionsByPins(['auth', 'security'])` - Fetch only relevant sections
|
|
64
|
-
|
|
65
|
-
## Files That Must Have PINs
|
|
66
|
-
|
|
67
|
-
| File | Required PINs |
|
|
68
|
-
|------|---------------|
|
|
69
|
-
| `decisions.md` | Per coding rule/pattern |
|
|
70
|
-
| `app-map.md` | Per component/screen |
|
|
71
|
-
| `product.md` | Per product section |
|
|
72
|
-
| `stack.md` | Per technology |
|
|
73
|
-
|
|
74
|
-
## Validation
|
|
75
|
-
|
|
76
|
-
Run `node scripts/flow-section-index.js --force` to regenerate the index.
|
|
77
|
-
Check `.workflow/state/section-index.json` for indexed sections and their pins.
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
alwaysApply: false
|
|
3
|
-
description: "Dual-repo management rules for wogi-flow and wogiflow-cloud"
|
|
4
|
-
globs: "package.json,lib/installer.js,lib/extension-points.js"
|
|
5
|
-
---
|
|
6
|
-
# Dual-Repo Management: wogi-flow + wogiflow-cloud
|
|
7
|
-
|
|
8
|
-
**Added**: 2026-02-28
|
|
9
|
-
**Source**: User directive — formalize dual-repo architecture decisions
|
|
10
|
-
|
|
11
|
-
## Repository Ownership
|
|
12
|
-
|
|
13
|
-
| Repo | Package | Visibility | Purpose |
|
|
14
|
-
|------|---------|-----------|---------|
|
|
15
|
-
| `wogi-flow` | `wogiflow` (npm) | Public (AGPL-3.0) | Free CLI, workflow engine, all local-only features |
|
|
16
|
-
| `wogiflow-cloud` | `@wogiflow/teams` (client), `wogiflow-cloud-server` (server) | Private | Teams backend, client hooks, dashboard, portal logic |
|
|
17
|
-
| `wogiflow-portal` | N/A (static site) | Public | wogi.ai — landing page, login, signup, knowledge base |
|
|
18
|
-
|
|
19
|
-
## Hard Rule: No Teams Code in the Free Repo
|
|
20
|
-
|
|
21
|
-
Team-specific logic MUST NEVER appear in `wogi-flow`. This includes:
|
|
22
|
-
- Auth/login UI beyond the thin `wogi login`/`wogi logout` adapter
|
|
23
|
-
- Sync engines, presence, real-time features
|
|
24
|
-
- Team CRUD, roles, permissions
|
|
25
|
-
- Dashboard pages
|
|
26
|
-
- Server-side API routes
|
|
27
|
-
|
|
28
|
-
The free repo provides **extension points** (hooks in `lib/extension-points.js`) that the cloud client plugs into. The adapter pattern is:
|
|
29
|
-
- `wogi-flow` exports hook interfaces and config schema
|
|
30
|
-
- `@wogiflow/teams` imports those interfaces and adds team behavior
|
|
31
|
-
- All team logic executes from `@wogiflow/teams`, never from `wogiflow` core
|
|
32
|
-
|
|
33
|
-
## Version Management
|
|
34
|
-
|
|
35
|
-
### Independent Versions, Mutual Awareness
|
|
36
|
-
|
|
37
|
-
Each repo has its own semver version. They are NOT locked together.
|
|
38
|
-
|
|
39
|
-
- `wogi-flow` → `package.json` version (currently 1.6.0)
|
|
40
|
-
- `wogiflow-cloud` server → `packages/server/package.json` version (currently 0.1.0)
|
|
41
|
-
- `@wogiflow/teams` client → `packages/client/package.json` version (currently 0.1.0)
|
|
42
|
-
|
|
43
|
-
### Cross-Repo Version File
|
|
44
|
-
|
|
45
|
-
Each repo maintains a `.workflow/state/partner-versions.json` that records the last-known version of the other repo:
|
|
46
|
-
|
|
47
|
-
```json
|
|
48
|
-
// In wogi-flow:
|
|
49
|
-
{
|
|
50
|
-
"self": { "package": "wogiflow", "version": "1.6.0" },
|
|
51
|
-
"partners": {
|
|
52
|
-
"wogiflow-cloud-server": { "version": "0.1.0", "checkedAt": "2026-02-28" },
|
|
53
|
-
"wogiflow-teams-client": { "version": "0.1.0", "minCompatible": "1.5.0", "checkedAt": "2026-02-28" }
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// In wogiflow-cloud:
|
|
58
|
-
{
|
|
59
|
-
"self": { "package": "wogiflow-cloud", "version": "0.1.0" },
|
|
60
|
-
"partners": {
|
|
61
|
-
"wogiflow": { "version": "1.6.0", "checkedAt": "2026-02-28" }
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
**Update rule**: When releasing either repo, update `partner-versions.json` in BOTH repos.
|
|
67
|
-
|
|
68
|
-
### Compatibility Contract
|
|
69
|
-
|
|
70
|
-
The `@wogiflow/teams` client declares its minimum compatible `wogiflow` version via peerDependencies:
|
|
71
|
-
|
|
72
|
-
```json
|
|
73
|
-
"peerDependencies": {
|
|
74
|
-
"wogiflow": ">=1.5.0"
|
|
75
|
-
}
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
**When to bump the minimum**:
|
|
79
|
-
- When the free repo removes or renames an exported function that the client uses
|
|
80
|
-
- When the free repo changes the shape of config.json, ready.json, or other state files
|
|
81
|
-
- When the free repo changes hook interfaces (entry point signatures, event payloads)
|
|
82
|
-
|
|
83
|
-
**When NOT to bump**:
|
|
84
|
-
- New features added to the free repo (additive changes are always compatible)
|
|
85
|
-
- Internal refactoring that doesn't change exports
|
|
86
|
-
|
|
87
|
-
## Interface Contract (Public API Surface)
|
|
88
|
-
|
|
89
|
-
The cloud client depends on these interfaces from `wogi-flow`. Changes to any of these require updating the client:
|
|
90
|
-
|
|
91
|
-
### Exported Functions (from scripts/)
|
|
92
|
-
- `flow-utils.js`: `getConfig()`, `safeJsonParse()`, `writeJson()`, `generateTaskId()`, `validateTaskId()`, `PATHS`, `getReadyData()`, `saveReadyData()`
|
|
93
|
-
- `flow-session-state.js`: `trackTaskStart()`, `trackBypassAttempt()`
|
|
94
|
-
- `flow-memory-blocks.js`: `setCurrentTask()`
|
|
95
|
-
|
|
96
|
-
### Hook Interfaces (entry point contracts)
|
|
97
|
-
- `PreToolUse` hooks receive: `{ tool, toolInput }` via stdin JSON
|
|
98
|
-
- `PostToolUse` hooks receive: `{ tool, toolInput, toolResult }` via stdin JSON
|
|
99
|
-
- `TaskCompleted` hooks receive: `{ taskId }` via stdin JSON
|
|
100
|
-
- `SessionStart`/`SessionEnd` hooks receive: `{}` via stdin JSON
|
|
101
|
-
|
|
102
|
-
### State File Formats
|
|
103
|
-
- `ready.json`: `{ inProgress: [], ready: [], blocked: [], recentlyCompleted: [], backlog: [] }`
|
|
104
|
-
- `config.json`: Schema documented in `config.schema.json`
|
|
105
|
-
- `decisions.md`: Markdown with `## Section` / `### Rule` structure
|
|
106
|
-
- `session-state.json`: `{ taskId, status, lastBriefingAt, ... }`
|
|
107
|
-
|
|
108
|
-
### Config Keys Used by Cloud
|
|
109
|
-
- `hooks.rules.*` — all hook toggle keys
|
|
110
|
-
- `enforcement.*` — strict mode, task gating
|
|
111
|
-
- `semanticMatching.*` — reuse detection thresholds
|
|
112
|
-
|
|
113
|
-
**When modifying any of the above**: Check wogiflow-cloud for consumers BEFORE releasing.
|
|
114
|
-
|
|
115
|
-
## Change Propagation Rules
|
|
116
|
-
|
|
117
|
-
### OSS Change → Does Cloud Need Updating?
|
|
118
|
-
|
|
119
|
-
| Change Type | Cloud Impact | Action Required |
|
|
120
|
-
|-------------|-------------|-----------------|
|
|
121
|
-
| New feature (additive) | None | No action needed |
|
|
122
|
-
| Bug fix (internal) | None | No action needed |
|
|
123
|
-
| Exported function renamed/removed | BREAKING | Update client, bump peerDep minimum |
|
|
124
|
-
| State file format changed | BREAKING | Update client parsers |
|
|
125
|
-
| Hook interface changed | BREAKING | Update client hooks |
|
|
126
|
-
| Config key renamed/removed | BREAKING | Update client config readers |
|
|
127
|
-
| New config key added | None (additive) | Client can optionally use it |
|
|
128
|
-
|
|
129
|
-
### Cloud Change → Does OSS Need Updating?
|
|
130
|
-
|
|
131
|
-
| Change Type | OSS Impact | Action Required |
|
|
132
|
-
|-------------|-----------|-----------------|
|
|
133
|
-
| New server feature | None | No action needed |
|
|
134
|
-
| New client hook | None | No action needed |
|
|
135
|
-
| Client needs new OSS export | REQUIRES | Add export to OSS, release OSS first |
|
|
136
|
-
| Dashboard changes | None | Entirely separate |
|
|
137
|
-
|
|
138
|
-
### Release Order
|
|
139
|
-
|
|
140
|
-
1. **OSS first**: If the cloud needs a new OSS feature, release OSS first
|
|
141
|
-
2. **Cloud follows**: Cloud releases independently, referencing the OSS version in peerDeps
|
|
142
|
-
3. **Never**: Release cloud with a dependency on an unreleased OSS version
|
|
143
|
-
|
|
144
|
-
```
|
|
145
|
-
OSS v1.7.0 (adds new export)
|
|
146
|
-
↓
|
|
147
|
-
Cloud client v0.2.0 (uses new export, peerDep bumped to >=1.7.0)
|
|
148
|
-
↓
|
|
149
|
-
Cloud server v0.2.0 (may or may not change)
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
## Web Properties
|
|
153
|
-
|
|
154
|
-
| Property | Repo | Purpose |
|
|
155
|
-
|----------|------|---------|
|
|
156
|
-
| wogi.ai (main site) | `wogiflow-portal` | Landing, login, signup, knowledge base |
|
|
157
|
-
| Dashboard (admin UI) | `wogiflow-cloud/packages/dashboard/` | Team admin — served by cloud server |
|
|
158
|
-
|
|
159
|
-
The portal is a separate deployment from the dashboard. The portal is public-facing (marketing + auth). The dashboard is authenticated (team management).
|
|
160
|
-
|
|
161
|
-
## Verification Checklist (Before Any Release)
|
|
162
|
-
|
|
163
|
-
### Releasing wogi-flow (OSS):
|
|
164
|
-
1. Check `partner-versions.json` — is cloud version current?
|
|
165
|
-
2. If any exported function/interface changed: grep wogiflow-cloud for consumers
|
|
166
|
-
3. Run `node --check` on all modified scripts
|
|
167
|
-
4. Follow GitHub Release Workflow (decisions.md)
|
|
168
|
-
5. After release: update `partner-versions.json` in wogiflow-cloud
|
|
169
|
-
|
|
170
|
-
### Releasing wogiflow-cloud:
|
|
171
|
-
1. Check `partner-versions.json` — is OSS version current?
|
|
172
|
-
2. Verify `peerDependencies.wogiflow` range includes current OSS version
|
|
173
|
-
3. If client needs new OSS export: release OSS first
|
|
174
|
-
4. After release: update `partner-versions.json` in wogi-flow
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
alwaysApply: false
|
|
3
|
-
description: "Cleanup checklist when refactoring or renaming features"
|
|
4
|
-
globs:
|
|
5
|
-
- "scripts/*.js"
|
|
6
|
-
- ".claude/skills/**/*"
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# Feature Refactoring Cleanup
|
|
10
|
-
|
|
11
|
-
When refactoring, renaming, or replacing a feature, ensure complete cleanup of the old implementation.
|
|
12
|
-
|
|
13
|
-
## Mandatory Cleanup Checklist
|
|
14
|
-
|
|
15
|
-
When a feature is refactored or renamed, you MUST:
|
|
16
|
-
|
|
17
|
-
### 1. Remove Old Code
|
|
18
|
-
- [ ] Delete old script files (e.g., `flow-old-feature.js`)
|
|
19
|
-
- [ ] Remove old skill directories (e.g., `.claude/skills/old-feature/`)
|
|
20
|
-
- [ ] Remove old hook files if applicable
|
|
21
|
-
|
|
22
|
-
### 2. Update Configuration
|
|
23
|
-
- [ ] Rename config keys (e.g., `oldFeature` → `newFeature`)
|
|
24
|
-
- [ ] Remove from `skills.installed` array if skill was removed
|
|
25
|
-
- [ ] Update any feature flags
|
|
26
|
-
|
|
27
|
-
### 3. Update Documentation
|
|
28
|
-
- [ ] Rename/update doc files in `.claude/docs/`
|
|
29
|
-
- [ ] Update command references in `commands.md`
|
|
30
|
-
- [ ] Update skill-matching.md if skill changed
|
|
31
|
-
- [ ] Search for old name in all `.md` files
|
|
32
|
-
|
|
33
|
-
### 4. Clean References
|
|
34
|
-
- [ ] Search codebase: `grep -r "old-feature-name" .`
|
|
35
|
-
- [ ] Update imports in dependent scripts
|
|
36
|
-
- [ ] Update any hardcoded references
|
|
37
|
-
|
|
38
|
-
### 5. Update State Files
|
|
39
|
-
- [ ] Clean `.workflow/state/` of old state files
|
|
40
|
-
- [ ] Update `ready.json` if tasks reference old feature
|
|
41
|
-
- [ ] Archive old change specs
|
|
42
|
-
|
|
43
|
-
## Search Commands
|
|
44
|
-
|
|
45
|
-
Run these to find lingering references:
|
|
46
|
-
|
|
47
|
-
```bash
|
|
48
|
-
# Find all references to old feature
|
|
49
|
-
grep -r "old-feature-name" --include="*.js" --include="*.md" --include="*.json" .
|
|
50
|
-
|
|
51
|
-
# Find in config
|
|
52
|
-
grep "oldFeatureName" .workflow/config.json
|
|
53
|
-
|
|
54
|
-
# Find skill references
|
|
55
|
-
grep -r "old-feature" .claude/
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
## Why This Matters
|
|
59
|
-
|
|
60
|
-
Incomplete cleanup causes:
|
|
61
|
-
- **Confusion**: Old commands/skills appear to work but don't
|
|
62
|
-
- **Bloat**: Dead code accumulates
|
|
63
|
-
- **Errors**: Old references cause runtime failures
|
|
64
|
-
- **Documentation drift**: Docs describe non-existent features
|
|
65
|
-
|
|
66
|
-
## Example: transcript-digestion → long-input-gate
|
|
67
|
-
|
|
68
|
-
When this refactoring happened without proper cleanup:
|
|
69
|
-
|
|
70
|
-
| Artifact | Status | Should Have Been |
|
|
71
|
-
|----------|--------|------------------|
|
|
72
|
-
| `.claude/skills/transcript-digestion/` | Left behind | Deleted |
|
|
73
|
-
| `config.transcriptDigestion` | Left as-is | Renamed to `longInputGate` |
|
|
74
|
-
| `skills.installed` array | Still listed | Removed |
|
|
75
|
-
| `skill-matching.md` | Old references | Updated |
|
|
76
|
-
| `transcript-digestion.md` doc | Still existed | Renamed/rewritten |
|
|
77
|
-
|
|
78
|
-
## Automation Opportunity
|
|
79
|
-
|
|
80
|
-
Consider adding a `flow refactor-cleanup <old-name> <new-name>` command that:
|
|
81
|
-
1. Searches for all references
|
|
82
|
-
2. Shows what needs updating
|
|
83
|
-
3. Optionally auto-updates simple cases
|
|
84
|
-
|
|
85
|
-
---
|
|
86
|
-
|
|
87
|
-
Last updated: 2026-01-14
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: "GitHub release workflow - prevents race conditions in npm publish"
|
|
3
|
-
alwaysApply: false
|
|
4
|
-
globs: package.json
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# GitHub Release Workflow
|
|
8
|
-
|
|
9
|
-
**Source**: Repeated failures (10+ times) in npm publish automation
|
|
10
|
-
**Priority**: Critical - prevents wasted releases and broken npm versions
|
|
11
|
-
|
|
12
|
-
## Problem
|
|
13
|
-
|
|
14
|
-
Running `git push` followed immediately by `gh release create` causes a race condition. The release tag gets created on the remote's HEAD before the push fully propagates, pointing to an old commit.
|
|
15
|
-
|
|
16
|
-
## Pre-Release Quality Gate (MANDATORY)
|
|
17
|
-
|
|
18
|
-
Before ANY release, verify the codebase is in a releasable state:
|
|
19
|
-
|
|
20
|
-
1. **Check outstanding findings**: Read `.workflow/state/last-review.json` — if unresolved critical/high findings exist, STOP and fix them first
|
|
21
|
-
2. **Run lint** (if configured): `npm run lint`
|
|
22
|
-
3. **Run typecheck** (if configured): `npm run typecheck`
|
|
23
|
-
4. **Verify no uncommitted changes**: `git status` should be clean
|
|
24
|
-
|
|
25
|
-
The `preRelease` and `outstandingFindings` quality gates in `flow-done.js` enforce this automatically for `release` type tasks. For manual releases, check these yourself.
|
|
26
|
-
|
|
27
|
-
## Correct Procedure
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
# 0. Verify codebase is releasable (pre-release gate)
|
|
31
|
-
# (automated by flow-done.js for release-type tasks)
|
|
32
|
-
|
|
33
|
-
# 1. Push commits first
|
|
34
|
-
git push origin master
|
|
35
|
-
|
|
36
|
-
# 2. Create tag LOCALLY on the correct commit
|
|
37
|
-
git tag vX.Y.Z HEAD
|
|
38
|
-
|
|
39
|
-
# 3. Push the tag explicitly
|
|
40
|
-
git push origin vX.Y.Z
|
|
41
|
-
|
|
42
|
-
# 4. THEN create the release (it will use the existing tag)
|
|
43
|
-
gh release create vX.Y.Z --title "vX.Y.Z" --notes "..."
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
## Never Do This
|
|
47
|
-
|
|
48
|
-
```bash
|
|
49
|
-
# BAD - race condition, tag may point to wrong commit
|
|
50
|
-
git push origin master && gh release create vX.Y.Z ...
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
## Recovery Procedure
|
|
54
|
-
|
|
55
|
-
If a release fails with wrong version:
|
|
56
|
-
|
|
57
|
-
1. Delete the bad release: `gh release delete vX.Y.Z --yes`
|
|
58
|
-
2. Delete the bad remote tag: `git push origin --delete vX.Y.Z`
|
|
59
|
-
3. Delete local tag if exists: `git tag -d vX.Y.Z`
|
|
60
|
-
4. Follow the correct procedure above
|
|
61
|
-
|
|
62
|
-
## Verification
|
|
63
|
-
|
|
64
|
-
Before creating the release, verify:
|
|
65
|
-
```bash
|
|
66
|
-
git show vX.Y.Z --quiet --format="%H" # Should match HEAD
|
|
67
|
-
git show vX.Y.Z:package.json | grep version # Should show X.Y.Z
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
---
|
|
71
|
-
Last updated: 2026-01-30
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
globs: scripts/flow-model*.js
|
|
3
|
-
alwaysApply: false
|
|
4
|
-
description: "Model management architecture - two separate systems for different purposes"
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Model Management Architecture
|
|
8
|
-
|
|
9
|
-
**Context**: Phase 1 introduced model registry and stats system alongside existing model-adapter.
|
|
10
|
-
|
|
11
|
-
## Two Model Systems
|
|
12
|
-
|
|
13
|
-
### 1. flow-model-adapter.js - Prompt Adaptation
|
|
14
|
-
|
|
15
|
-
- `getCurrentModel()` returns normalized model name (string)
|
|
16
|
-
- Focus: Per-model prompt adjustments, learning, and corrections
|
|
17
|
-
- Imports: Used by flow-knowledge-router.js
|
|
18
|
-
|
|
19
|
-
### 2. flow-models.js - Registry and Stats
|
|
20
|
-
|
|
21
|
-
- `getCurrentModel()` returns `{name, info, source}` object
|
|
22
|
-
- Focus: Model listing, routing recommendations, cost tracking
|
|
23
|
-
- Standalone CLI commands: `flow models [subcommand]`
|
|
24
|
-
|
|
25
|
-
## Design Decision
|
|
26
|
-
|
|
27
|
-
**Keep them separate** because:
|
|
28
|
-
- Different return types serve different consumers
|
|
29
|
-
- Adapter system needs just the name for pattern matching
|
|
30
|
-
- Registry system needs full model metadata for display/routing
|
|
31
|
-
- Merging would create unnecessary coupling
|
|
32
|
-
|
|
33
|
-
## Future Consideration
|
|
34
|
-
|
|
35
|
-
Could extract shared model detection logic into a common utility if they drift apart, but avoid premature abstraction.
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: "Patterns for modifying WogiFlow itself (scripts, templates, config)"
|
|
3
|
-
alwaysApply: false
|
|
4
|
-
globs: "scripts/**,*.workflow/**,.claude/**,templates/**,agents/**,lib/**"
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# WogiFlow Self-Maintenance Patterns
|
|
8
|
-
|
|
9
|
-
When modifying WogiFlow's own code (scripts/, templates/, config, hooks), follow these patterns.
|
|
10
|
-
|
|
11
|
-
## 1. Template-First Changes
|
|
12
|
-
|
|
13
|
-
CLAUDE.md is **generated**, not hand-edited. Changes must go through the template system:
|
|
14
|
-
|
|
15
|
-
```
|
|
16
|
-
.workflow/templates/claude-md.hbs # Main template
|
|
17
|
-
.workflow/templates/partials/*.hbs # Partial templates
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
After editing templates, regenerate:
|
|
21
|
-
```bash
|
|
22
|
-
node scripts/flow-bridge.js sync claude-code
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
**Never edit CLAUDE.md directly** - changes will be overwritten on next sync.
|
|
26
|
-
|
|
27
|
-
## 2. Three-Layer Hook Architecture
|
|
28
|
-
|
|
29
|
-
All hooks follow: Entry → Core → Adapter
|
|
30
|
-
|
|
31
|
-
```
|
|
32
|
-
scripts/hooks/entry/claude-code/<name>.js # CLI-specific entry point
|
|
33
|
-
scripts/hooks/core/<name>.js # CLI-agnostic logic
|
|
34
|
-
scripts/hooks/adapters/claude-code.js # Transform results
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
When adding/modifying hooks:
|
|
38
|
-
- Logic goes in `core/` (not entry)
|
|
39
|
-
- Entry files only parse input and call core
|
|
40
|
-
- Register hook in `.claude/settings.local.json`
|
|
41
|
-
- Add config toggle in `.workflow/config.json` under `hooks.rules`
|
|
42
|
-
|
|
43
|
-
## 3. Config Changes Need Documentation
|
|
44
|
-
|
|
45
|
-
When adding config keys:
|
|
46
|
-
- Use `_comment_<keyName>` for inline documentation of non-obvious settings
|
|
47
|
-
- Update config.schema.json if it exists
|
|
48
|
-
- Ensure `lib/installer.js` handles the new key for fresh installs
|
|
49
|
-
|
|
50
|
-
## 4. State File Templates
|
|
51
|
-
|
|
52
|
-
For files in `.workflow/state/` that target projects need:
|
|
53
|
-
- Create both the file AND a `.template` version
|
|
54
|
-
- Templates go in `.workflow/state/<name>.template` (for init/onboard)
|
|
55
|
-
- Also add to `templates/` directory (for npm distribution)
|
|
56
|
-
|
|
57
|
-
## 5. Slash Commands Are Flat Files
|
|
58
|
-
|
|
59
|
-
Slash commands in `.claude/commands/` must be flat `.md` files:
|
|
60
|
-
```
|
|
61
|
-
.claude/commands/wogi-start.md ← Correct (flat file)
|
|
62
|
-
.claude/commands/wogi-start/ ← Wrong (directory)
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
## 6. Two Agent Directories
|
|
66
|
-
|
|
67
|
-
| Directory | Purpose | Used By |
|
|
68
|
-
|-----------|---------|---------|
|
|
69
|
-
| `agents/` | 11 persona files | Health checks, CLI |
|
|
70
|
-
| `.workflow/agents/` | Review checklists | wogi-review |
|
|
71
|
-
|
|
72
|
-
Don't confuse them. `agents/security.md` (persona) is different from `.workflow/agents/security.md` (OWASP checklist).
|
|
73
|
-
|
|
74
|
-
## 7. Regression Prevention
|
|
75
|
-
|
|
76
|
-
When modifying flow-*.js scripts:
|
|
77
|
-
- Run `node --check scripts/<file>.js` after edits
|
|
78
|
-
- WogiFlow has no test suite - syntax checking is the safety net
|
|
79
|
-
- Check for circular dependencies when moving shared functions
|
|
80
|
-
|
|
81
|
-
## 8. Feature Refactoring Cleanup
|
|
82
|
-
|
|
83
|
-
When renaming/replacing a feature, follow the full checklist in `.claude/rules/architecture/feature-refactoring-cleanup.md`. Key steps:
|
|
84
|
-
- Remove old script files
|
|
85
|
-
- Update config keys
|
|
86
|
-
- Update documentation references
|
|
87
|
-
- Search all `.md` files for old name
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
globs: src/components/**/*
|
|
3
|
-
alwaysApply: false
|
|
4
|
-
description: "Component reuse policy - always check app-map.md before creating components"
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Component Reuse Policy
|
|
8
|
-
|
|
9
|
-
**Rule**: Always check `app-map.md` before creating any component.
|
|
10
|
-
|
|
11
|
-
## Priority Order
|
|
12
|
-
|
|
13
|
-
1. **Use existing** - Check if component already exists in app-map
|
|
14
|
-
2. **Add variant** - Extend existing component with a new variant
|
|
15
|
-
3. **Extend** - Create a wrapper/HOC around existing component
|
|
16
|
-
4. **Create new** - Only as last resort
|
|
17
|
-
|
|
18
|
-
## Before Creating Components
|
|
19
|
-
|
|
20
|
-
```bash
|
|
21
|
-
# Check app-map first
|
|
22
|
-
cat .workflow/state/app-map.md | grep -i "button"
|
|
23
|
-
|
|
24
|
-
# Or search codebase
|
|
25
|
-
grep -r "Button" src/components/
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
## Variant vs New Component
|
|
29
|
-
|
|
30
|
-
Prefer variants when:
|
|
31
|
-
- Same base functionality, different appearance
|
|
32
|
-
- Same HTML structure, different styling
|
|
33
|
-
- Same component, different size/color/state
|
|
34
|
-
|
|
35
|
-
Create new component when:
|
|
36
|
-
- Fundamentally different functionality
|
|
37
|
-
- Different DOM structure
|
|
38
|
-
- Different state management
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
alwaysApply: true
|
|
3
|
-
description: "Naming conventions for files and code variants"
|
|
4
|
-
globs: "**/*.{js,ts,jsx,tsx,mjs,cjs}"
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Naming Conventions
|
|
8
|
-
|
|
9
|
-
## File Names
|
|
10
|
-
|
|
11
|
-
Use **kebab-case** for all file names in this project.
|
|
12
|
-
|
|
13
|
-
Examples:
|
|
14
|
-
- `flow-health.js` (correct)
|
|
15
|
-
- `flowHealth.js` (incorrect)
|
|
16
|
-
- `flow_health.js` (incorrect)
|
|
17
|
-
|
|
18
|
-
## Variant Names (UI Projects Only)
|
|
19
|
-
|
|
20
|
-
When working on projects with UI components, use consistent variant names:
|
|
21
|
-
|
|
22
|
-
| Category | Values |
|
|
23
|
-
|----------|--------|
|
|
24
|
-
| Size | `sm`, `md`, `lg`, `xl` |
|
|
25
|
-
| Intent | `primary`, `secondary`, `danger`, `success`, `warning` |
|
|
26
|
-
| State | `default`, `hover`, `active`, `disabled` |
|
|
27
|
-
|
|
28
|
-
Skip this section for backend-only or library projects (no UI components).
|
|
29
|
-
|
|
30
|
-
## Catch Block Variables
|
|
31
|
-
|
|
32
|
-
Use `err` for all catch blocks in this codebase.
|
|
33
|
-
|
|
34
|
-
**Avoid**: `e`, `error`, `ex`, `exception` - these cause confusion with loop variables.
|
|
35
|
-
|
|
36
|
-
```javascript
|
|
37
|
-
// Good
|
|
38
|
-
try {
|
|
39
|
-
doSomething();
|
|
40
|
-
} catch (err) {
|
|
41
|
-
console.error(err.message);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Bad - 'e' conflicts with common iterator variables
|
|
45
|
-
try {
|
|
46
|
-
items.map(e => e.value); // 'e' used as iterator
|
|
47
|
-
} catch (e) {
|
|
48
|
-
console.error(e.message); // Easy to confuse with iterator 'e'
|
|
49
|
-
}
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
**Reason**: Standardizing on `err` prevents mix-ups when `.map(e => ...)` is used nearby.
|
|
53
|
-
|
|
54
|
-
### Unused Catch Variables
|
|
55
|
-
|
|
56
|
-
When the catch block intentionally ignores the error, prefix with underscore: `_err`.
|
|
57
|
-
|
|
58
|
-
```javascript
|
|
59
|
-
// Good - _err signals "intentionally unused"
|
|
60
|
-
try {
|
|
61
|
-
JSON.parse(input);
|
|
62
|
-
} catch (_err) {
|
|
63
|
-
return defaultValue;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// Bad - looks like a bug (unused variable without underscore)
|
|
67
|
-
try {
|
|
68
|
-
JSON.parse(input);
|
|
69
|
-
} catch (err) {
|
|
70
|
-
return defaultValue;
|
|
71
|
-
}
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
This convention is used across 100+ files in the codebase and satisfies no-unused-vars lint rules.
|
|
75
|
-
|
|
76
|
-
## Default Value Operators: `||` vs `??`
|
|
77
|
-
|
|
78
|
-
Use **nullish coalescing (`??`)** for defaults where the left operand could legitimately be `0`, `false`, or `""`.
|
|
79
|
-
|
|
80
|
-
Use **logical OR (`||`)** only when falsy values (0, false, empty string) should genuinely fall through to the default.
|
|
81
|
-
|
|
82
|
-
```javascript
|
|
83
|
-
// Use ?? — timeout=0 is valid (means "no timeout"), not "use default"
|
|
84
|
-
this.timeout = options.timeout ?? TIMEOUTS.HTTP_DEFAULT;
|
|
85
|
-
|
|
86
|
-
// Use ?? — numeric config values where 0 is meaningful
|
|
87
|
-
const retries = config.maxRetries ?? 3;
|
|
88
|
-
const threshold = config.similarityThreshold ?? 0.5;
|
|
89
|
-
|
|
90
|
-
// Use ?? — boolean config where false is the intended value
|
|
91
|
-
const strictMode = config.enforcement?.strictMode ?? false;
|
|
92
|
-
|
|
93
|
-
// Use ?? — array/object defaults guarding against null/undefined
|
|
94
|
-
const items = data.inProgress ?? [];
|
|
95
|
-
const settings = config.hybrid ?? {};
|
|
96
|
-
|
|
97
|
-
// Use || — empty string should fall through to a display default
|
|
98
|
-
const branch = status.git.branch || 'unknown';
|
|
99
|
-
|
|
100
|
-
// Use || — lookup fallback where undefined means "not found"
|
|
101
|
-
const name = cliNames[type] || type;
|
|
102
|
-
|
|
103
|
-
// Use || — join() returns "" for empty arrays, want a fallback message
|
|
104
|
-
const summary = facts.join('; ') || 'No data available';
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
**Rule of thumb**: If you are defaulting a config value, numeric parameter, boolean flag, or array/object from a potentially-null source, use `??`. If you are providing a display fallback where empty string should show a placeholder, use `||`.
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
alwaysApply: true
|
|
3
|
-
description: "Git workflow rules for merge conflicts, conventional commits, and branch management"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Git Workflow Rules
|
|
7
|
-
|
|
8
|
-
## Merge Conflict Resolution
|
|
9
|
-
|
|
10
|
-
When encountering merge conflicts:
|
|
11
|
-
|
|
12
|
-
1. **Understand both sides** before resolving. Read the full context of both changes.
|
|
13
|
-
2. **Prefer the newer implementation** when both sides modify the same logic, unless the older version has test coverage the newer lacks.
|
|
14
|
-
3. **Never silently discard changes** — if unsure, ask the user which side to keep.
|
|
15
|
-
4. **After resolving**: Run lint and typecheck on resolved files before committing.
|
|
16
|
-
5. **Conflict markers**: If you see `<<<<<<<`, `=======`, `>>>>>>>` in any file, resolve them before any other work.
|
|
17
|
-
|
|
18
|
-
```bash
|
|
19
|
-
# Check for unresolved conflicts
|
|
20
|
-
git diff --check
|
|
21
|
-
|
|
22
|
-
# After resolving
|
|
23
|
-
git add <resolved-files>
|
|
24
|
-
git commit -m "fix: resolve merge conflicts in <description>"
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## Conventional Commit Format
|
|
28
|
-
|
|
29
|
-
All commits MUST use conventional commit format:
|
|
30
|
-
|
|
31
|
-
```
|
|
32
|
-
<type>(<scope>): <description>
|
|
33
|
-
|
|
34
|
-
[optional body]
|
|
35
|
-
|
|
36
|
-
[optional footer]
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
### Types
|
|
40
|
-
|
|
41
|
-
| Type | When to use |
|
|
42
|
-
|------|------------|
|
|
43
|
-
| `feat` | New feature or capability |
|
|
44
|
-
| `fix` | Bug fix |
|
|
45
|
-
| `docs` | Documentation only |
|
|
46
|
-
| `style` | Formatting, whitespace (no logic change) |
|
|
47
|
-
| `refactor` | Code change that neither fixes a bug nor adds a feature |
|
|
48
|
-
| `perf` | Performance improvement |
|
|
49
|
-
| `test` | Adding or updating tests |
|
|
50
|
-
| `chore` | Build process, tooling, dependencies |
|
|
51
|
-
|
|
52
|
-
### Examples
|
|
53
|
-
|
|
54
|
-
```
|
|
55
|
-
feat(hooks): add InstructionsLoaded hook for rule conflict detection
|
|
56
|
-
fix(routing): clear routing flag when user invokes /wogi-* commands
|
|
57
|
-
docs(readme): update installation instructions for v1.8
|
|
58
|
-
refactor(bridge): extract hash comparison to shared utility
|
|
59
|
-
chore(deps): bump eslint to v9.x
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
### Scope
|
|
63
|
-
|
|
64
|
-
Use the module or feature area: `hooks`, `bridge`, `routing`, `skills`, `plugins`, `config`, `cli`, `docs`.
|
|
65
|
-
|
|
66
|
-
## Pre-Commit Review
|
|
67
|
-
|
|
68
|
-
Before committing, always:
|
|
69
|
-
1. Run `git diff --staged` to review what you're about to commit
|
|
70
|
-
2. Verify no secrets, credentials, or `.env` files are staged
|
|
71
|
-
3. Verify no debug/console.log statements left in production code
|
|
72
|
-
4. Run validation (lint, typecheck) on changed files
|
|
73
|
-
|
|
74
|
-
## Stash Usage
|
|
75
|
-
|
|
76
|
-
Use `git stash` when:
|
|
77
|
-
- Switching context to a different task mid-work
|
|
78
|
-
- Pulling changes that might conflict with local work
|
|
79
|
-
- Testing something on a clean working tree
|
|
80
|
-
|
|
81
|
-
```bash
|
|
82
|
-
git stash push -m "WIP: description of work" # Save with message
|
|
83
|
-
git stash pop # Restore and remove
|
|
84
|
-
git stash list # See all stashes
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
## Branch Naming
|
|
88
|
-
|
|
89
|
-
When creating branches (outside worktrees):
|
|
90
|
-
- Feature: `feat/<short-description>`
|
|
91
|
-
- Bugfix: `fix/<short-description>`
|
|
92
|
-
- WogiFlow worktrees use `wogi-task-<taskId>` automatically
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
alwaysApply: true
|
|
3
|
-
description: "Temp files, prompts, instructions, and scratch content must go in .workflow/scratch/"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Scratch Directory for Temporary Files
|
|
7
|
-
|
|
8
|
-
## Rule
|
|
9
|
-
|
|
10
|
-
When creating temporary, scratch, or ephemeral files — such as prompts for other projects, instructions, notes, drafts, exported configs, or any content that is NOT a permanent part of the codebase — **always write them to `.workflow/scratch/`**.
|
|
11
|
-
|
|
12
|
-
## Why
|
|
13
|
-
|
|
14
|
-
Without this rule, Claude creates .md files, .txt files, and other scratch content in random locations (project root, src/, docs/, etc.). This pollutes the project with files that:
|
|
15
|
-
- Have no designated location, so users don't know where to find them
|
|
16
|
-
- Don't get cleaned up, accumulating over time
|
|
17
|
-
- May accidentally get committed to version control
|
|
18
|
-
- Make `git status` noisy with untracked files
|
|
19
|
-
|
|
20
|
-
## How
|
|
21
|
-
|
|
22
|
-
```javascript
|
|
23
|
-
// Use PATHS.scratch for temp file locations
|
|
24
|
-
const { PATHS } = require('./flow-paths');
|
|
25
|
-
const outputPath = path.join(PATHS.scratch, 'my-temp-file.md');
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
Or in natural language: "Save this to `.workflow/scratch/filename.md`"
|
|
29
|
-
|
|
30
|
-
## Auto-Cleanup
|
|
31
|
-
|
|
32
|
-
The `.workflow/scratch/` directory is **automatically cleaned at session end** by the session-end hook. Files in this directory are ephemeral — they survive the current session but are removed when the session ends.
|
|
33
|
-
|
|
34
|
-
If a file needs to persist beyond a session, it belongs somewhere else:
|
|
35
|
-
- Specs → `.workflow/specs/`
|
|
36
|
-
- Changes → `.workflow/changes/`
|
|
37
|
-
- Documentation → project docs directory
|
|
38
|
-
- Configuration → `.workflow/` root
|
|
39
|
-
|
|
40
|
-
## What Goes in Scratch
|
|
41
|
-
|
|
42
|
-
- Prompts or instructions generated for other projects
|
|
43
|
-
- Draft content being reviewed before placement
|
|
44
|
-
- Temporary analysis output
|
|
45
|
-
- Export/import staging files
|
|
46
|
-
- Any file the user explicitly asks to "save somewhere" without specifying a location
|
|
47
|
-
|
|
48
|
-
## What Does NOT Go in Scratch
|
|
49
|
-
|
|
50
|
-
- Task specs (use `.workflow/specs/` or `.workflow/changes/`)
|
|
51
|
-
- Configuration files (use `.workflow/`)
|
|
52
|
-
- Source code (use the project's source directories)
|
|
53
|
-
- Documentation (use the project's docs directory)
|
|
54
|
-
- State files (use `.workflow/state/`)
|
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
alwaysApply: true
|
|
3
|
-
description: "Security patterns for file operations, JSON parsing, and path handling"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Security Patterns
|
|
7
|
-
|
|
8
|
-
Critical security patterns for this project.
|
|
9
|
-
|
|
10
|
-
## 1. File Read Safety
|
|
11
|
-
|
|
12
|
-
Always wrap `fs.readFileSync()` in try-catch, even after `fileExists()` check.
|
|
13
|
-
|
|
14
|
-
**Reason**: Race conditions, permission changes, symlink issues can still cause failures.
|
|
15
|
-
|
|
16
|
-
```javascript
|
|
17
|
-
// Good
|
|
18
|
-
try {
|
|
19
|
-
const content = fs.readFileSync(path, 'utf-8');
|
|
20
|
-
} catch (err) {
|
|
21
|
-
// Handle gracefully
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Bad - can still throw even if file existed
|
|
25
|
-
if (fs.existsSync(path)) {
|
|
26
|
-
const content = fs.readFileSync(path, 'utf-8');
|
|
27
|
-
}
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
## 2. JSON Parsing Safety
|
|
31
|
-
|
|
32
|
-
Use `safeJsonParse()` from flow-utils.js instead of raw `JSON.parse()`.
|
|
33
|
-
|
|
34
|
-
- Check for `__proto__`, `constructor`, `prototype` injection
|
|
35
|
-
- Validate parsed structure has expected fields before use
|
|
36
|
-
- Located in: `scripts/flow-utils.js`
|
|
37
|
-
|
|
38
|
-
```javascript
|
|
39
|
-
// Good
|
|
40
|
-
const config = safeJsonParse(filePath, {});
|
|
41
|
-
|
|
42
|
-
// Bad - vulnerable to prototype pollution
|
|
43
|
-
const config = JSON.parse(fs.readFileSync(filePath));
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
## 3. Template Substitution Safety
|
|
47
|
-
|
|
48
|
-
When implementing template substitution:
|
|
49
|
-
- Block access to `__proto__`, `constructor`, `prototype` keys
|
|
50
|
-
- Use `Object.prototype.hasOwnProperty.call()` for property access
|
|
51
|
-
- Example: See `applyTemplate()` in flow-prompt-composer.js
|
|
52
|
-
|
|
53
|
-
## 4. Path Safety
|
|
54
|
-
|
|
55
|
-
- Validate patterns before `path.join()` with user/config data
|
|
56
|
-
- Use `isPathWithinProject()` for defense-in-depth
|
|
57
|
-
- Glob-to-regex: Use `[^/]*` not `.*` to prevent path separator matching
|
|
58
|
-
|
|
59
|
-
```javascript
|
|
60
|
-
// Good
|
|
61
|
-
if (!isPathWithinProject(targetPath)) {
|
|
62
|
-
throw new Error('Path outside project');
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Bad - allows path traversal
|
|
66
|
-
const fullPath = path.join(baseDir, userInput);
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
## 5. Module Dependencies
|
|
70
|
-
|
|
71
|
-
- Check for circular dependencies when refactoring shared functions
|
|
72
|
-
- Node.js handles circular deps but can cause undefined exports during load
|
|
73
|
-
|
|
74
|
-
## 6. Claude Code Permission Patterns (2.1.7+)
|
|
75
|
-
|
|
76
|
-
When configuring permission rules in Claude Code, avoid overly permissive wildcards.
|
|
77
|
-
|
|
78
|
-
**Vulnerability fixed in 2.1.7**: Wildcard permission rules could match compound commands containing shell operators (`;`, `&&`, `||`, `|`).
|
|
79
|
-
|
|
80
|
-
**Destructive git commands** must NOT be auto-allowed. WogiFlow's `generateSettings()` scopes these to safe variants:
|
|
81
|
-
|
|
82
|
-
```javascript
|
|
83
|
-
// DANGEROUS - auto-allows destructive operations
|
|
84
|
-
"allow": "Bash(git reset *)" // matches git reset --hard
|
|
85
|
-
"allow": "Bash(git restore *)" // matches git restore . (discard all)
|
|
86
|
-
"allow": "Bash(git clean *)" // matches git clean -f
|
|
87
|
-
|
|
88
|
-
// SAFE - only non-destructive variants auto-allowed
|
|
89
|
-
"allow": "Bash(git reset HEAD *)" // unstage files only
|
|
90
|
-
"allow": "Bash(git reset --soft *)" // soft reset, preserves changes
|
|
91
|
-
"allow": "Bash(git restore --staged *)" // unstage files only
|
|
92
|
-
// git reset --hard, git restore ., git clean -f require manual approval
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
**Best practices:**
|
|
96
|
-
- Scope destructive commands to safe variants instead of blanket wildcards
|
|
97
|
-
- `git reset --hard`, `git restore .`, `git clean -f` should always require user approval
|
|
98
|
-
- Prefer semantic permission prompts over literal command matching
|
|
99
|
-
- Never allow broad patterns like `rm *` or `git *`
|
|
100
|
-
- Review permission rules after Claude Code updates
|
|
101
|
-
|
|
102
|
-
## 7. Windows Path Safety
|
|
103
|
-
|
|
104
|
-
On Windows, be aware of path-related issues:
|
|
105
|
-
|
|
106
|
-
- Temp directory paths may contain characters like `\t` or `\n` that could be misinterpreted as escape sequences
|
|
107
|
-
- Use raw strings or proper escaping when constructing paths
|
|
108
|
-
- Cloud sync tools (OneDrive, Dropbox) and antivirus may touch file timestamps without changing content
|
|
109
|
-
|
|
110
|
-
```javascript
|
|
111
|
-
// Good - use path.join() which handles platform differences
|
|
112
|
-
const tempPath = path.join(os.tmpdir(), 'myfile.txt');
|
|
113
|
-
|
|
114
|
-
// Bad - manual concatenation can break on Windows
|
|
115
|
-
const tempPath = os.tmpdir() + '/myfile.txt';
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
## 8. Shell Command Parameter Validation
|
|
119
|
-
|
|
120
|
-
When executing shell commands with dynamic parameters, always validate inputs.
|
|
121
|
-
|
|
122
|
-
**Risk**: Command injection via unvalidated parameters passed to execSync/spawn.
|
|
123
|
-
|
|
124
|
-
```javascript
|
|
125
|
-
// DANGEROUS - lang parameter not validated
|
|
126
|
-
execSync(`sg --pattern "${pattern}" --lang ${lang} --json "${path}"`);
|
|
127
|
-
|
|
128
|
-
// SAFER - validate against whitelist
|
|
129
|
-
const ALLOWED_LANGUAGES = new Set(['typescript', 'javascript', 'python', 'go']);
|
|
130
|
-
if (!ALLOWED_LANGUAGES.has(lang)) {
|
|
131
|
-
throw new Error(`Unsupported language: ${lang}`);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// BEST - use execFile with array arguments (no shell interpretation)
|
|
135
|
-
const { execFileSync } = require('child_process');
|
|
136
|
-
execFileSync('sg', ['--pattern', pattern, '--lang', lang, '--json', path]);
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
**Best practices:**
|
|
140
|
-
- Validate all dynamic parameters against allowlists
|
|
141
|
-
- Prefer `execFile`/`execFileSync` with array arguments over `exec`/`execSync` with template strings
|
|
142
|
-
- When using template strings, escape all user-controlled values
|
|
143
|
-
- Never interpolate user input directly into shell commands
|
|
144
|
-
|
|
145
|
-
## 9. Temp Directory Isolation (Claude Code 2.1.23+)
|
|
146
|
-
|
|
147
|
-
On shared systems (CI servers, multi-user machines), use per-user temp directories to prevent permission conflicts.
|
|
148
|
-
|
|
149
|
-
**Fixed in Claude Code 2.1.23**: Per-user temp directory isolation prevents permission conflicts.
|
|
150
|
-
|
|
151
|
-
```javascript
|
|
152
|
-
// Good - per-user isolation
|
|
153
|
-
const userId = process.getuid?.() ?? process.env.USER ?? process.env.USERNAME ?? 'default';
|
|
154
|
-
const tempDir = path.join(os.tmpdir(), `myapp-${userId}`);
|
|
155
|
-
|
|
156
|
-
// Bad - global temp path on shared systems
|
|
157
|
-
const tempDir = path.join(os.tmpdir(), 'myapp');
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
**Best practices:**
|
|
161
|
-
- Use UID on Unix systems (`process.getuid()`)
|
|
162
|
-
- Fall back to username environment variables on Windows
|
|
163
|
-
- Always provide a 'default' fallback for edge cases
|
|
164
|
-
- This pattern is used in `flow-worktree.js` for worktree isolation
|
|
165
|
-
|
|
166
|
-
## 10. Search/Grep Timeout Handling (Claude Code 2.1.23+)
|
|
167
|
-
|
|
168
|
-
**Fixed in Claude Code 2.1.23**: Ripgrep search timeouts now report errors instead of silently returning empty results.
|
|
169
|
-
|
|
170
|
-
**Impact on WogiFlow:** Component detection, auto-context loading, and pattern matching rely on search operations. Before 2.1.23, search timeouts could cause false negatives.
|
|
171
|
-
|
|
172
|
-
**Best practices:**
|
|
173
|
-
- Handle empty search results gracefully - they may indicate timeout
|
|
174
|
-
- Add retry logic for search-dependent operations
|
|
175
|
-
- Log warnings when searches return unexpectedly empty
|
|
176
|
-
- Consider fallback strategies (glob-based search if grep fails)
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
# Architecture
|
|
2
|
-
|
|
3
|
-
## Pattern
|
|
4
|
-
|
|
5
|
-
<!-- Detected during onboarding -->
|
|
6
|
-
<!-- Examples: MVC, Clean Architecture, DDD, Microservices, Monolith -->
|
|
7
|
-
|
|
8
|
-
## Structure
|
|
9
|
-
|
|
10
|
-
<!-- Project structure overview -->
|
|
11
|
-
<!-- Key directories and their purposes -->
|
|
12
|
-
|
|
13
|
-
## Key Decisions
|
|
14
|
-
|
|
15
|
-
<!-- Architecture decisions made for this project -->
|
|
16
|
-
<!-- Trade-offs and rationale -->
|
|
17
|
-
|
|
18
|
-
## Dependencies
|
|
19
|
-
|
|
20
|
-
<!-- Major dependencies and their purposes -->
|
|
21
|
-
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
*This file is auto-populated during `flow onboard`. Update manually as architecture evolves.*
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
# Tech Stack
|
|
2
|
-
|
|
3
|
-
## Framework
|
|
4
|
-
|
|
5
|
-
<!-- Primary framework (e.g., Next.js, NestJS, FastAPI) -->
|
|
6
|
-
|
|
7
|
-
## Language
|
|
8
|
-
|
|
9
|
-
<!-- Primary language (e.g., TypeScript, Python, Go) -->
|
|
10
|
-
|
|
11
|
-
## Database
|
|
12
|
-
|
|
13
|
-
<!-- Database system if applicable (e.g., PostgreSQL, MongoDB) -->
|
|
14
|
-
|
|
15
|
-
## Package Manager
|
|
16
|
-
|
|
17
|
-
<!-- npm, yarn, pnpm, pip, etc. -->
|
|
18
|
-
|
|
19
|
-
## Build Tools
|
|
20
|
-
|
|
21
|
-
<!-- Build and bundling tools (e.g., Vite, Webpack, esbuild) -->
|
|
22
|
-
|
|
23
|
-
## Testing
|
|
24
|
-
|
|
25
|
-
<!-- Test frameworks (e.g., Jest, Vitest, pytest) -->
|
|
26
|
-
|
|
27
|
-
## Other Tools
|
|
28
|
-
|
|
29
|
-
<!-- Linters, formatters, CI/CD tools -->
|
|
30
|
-
|
|
31
|
-
---
|
|
32
|
-
|
|
33
|
-
*This file is auto-populated during `flow onboard`. Update manually as stack evolves.*
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
# Testing
|
|
2
|
-
|
|
3
|
-
## Test Framework
|
|
4
|
-
|
|
5
|
-
<!-- Primary test framework (e.g., Jest, Vitest, pytest) -->
|
|
6
|
-
|
|
7
|
-
## Test Commands
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
# Run all tests
|
|
11
|
-
npm test
|
|
12
|
-
|
|
13
|
-
# Run tests in watch mode
|
|
14
|
-
npm run test:watch
|
|
15
|
-
|
|
16
|
-
# Run specific test file
|
|
17
|
-
npm test -- path/to/test.ts
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
## Test Structure
|
|
21
|
-
|
|
22
|
-
<!-- Where tests are located -->
|
|
23
|
-
<!-- Naming conventions -->
|
|
24
|
-
|
|
25
|
-
## Coverage
|
|
26
|
-
|
|
27
|
-
<!-- Coverage requirements if any -->
|
|
28
|
-
<!-- Coverage commands -->
|
|
29
|
-
|
|
30
|
-
## E2E Testing
|
|
31
|
-
|
|
32
|
-
<!-- E2E framework if used (e.g., Playwright, Cypress) -->
|
|
33
|
-
|
|
34
|
-
---
|
|
35
|
-
|
|
36
|
-
*This file is auto-populated during `flow onboard`. Update manually as testing strategy evolves.*
|