wogiflow 1.0.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/.workflow/agents/reviewer.md +81 -0
- package/.workflow/agents/security.md +94 -0
- package/.workflow/agents/story-writer.md +58 -0
- package/.workflow/bridges/base-bridge.js +395 -0
- package/.workflow/bridges/claude-bridge.js +434 -0
- package/.workflow/bridges/index.js +130 -0
- package/.workflow/lib/assumption-detector.js +481 -0
- package/.workflow/lib/config-substitution.js +371 -0
- package/.workflow/lib/failure-categories.js +478 -0
- package/.workflow/state/app-map.md.template +15 -0
- package/.workflow/state/architecture.md.template +24 -0
- package/.workflow/state/component-index.json.template +5 -0
- package/.workflow/state/decisions.md.template +15 -0
- package/.workflow/state/feedback-patterns.md.template +9 -0
- package/.workflow/state/knowledge-sync.json.template +6 -0
- package/.workflow/state/progress.md.template +14 -0
- package/.workflow/state/ready.json.template +7 -0
- package/.workflow/state/request-log.md.template +14 -0
- package/.workflow/state/session-state.json.template +11 -0
- package/.workflow/state/stack.md.template +33 -0
- package/.workflow/state/testing.md.template +36 -0
- package/.workflow/templates/claude-md.hbs +257 -0
- package/.workflow/templates/correction-report.md +67 -0
- package/.workflow/templates/gemini-md.hbs +52 -0
- package/README.md +1802 -0
- package/bin/flow +205 -0
- package/lib/index.js +33 -0
- package/lib/installer.js +467 -0
- package/lib/release-channel.js +269 -0
- package/lib/skill-registry.js +526 -0
- package/lib/upgrader.js +401 -0
- package/lib/utils.js +305 -0
- package/package.json +64 -0
- package/scripts/flow +985 -0
- package/scripts/flow-adaptive-learning.js +1259 -0
- package/scripts/flow-aggregate.js +488 -0
- package/scripts/flow-archive +133 -0
- package/scripts/flow-auto-context.js +1015 -0
- package/scripts/flow-auto-learn.js +615 -0
- package/scripts/flow-bridge.js +223 -0
- package/scripts/flow-browser-suggest.js +316 -0
- package/scripts/flow-bug.js +247 -0
- package/scripts/flow-cascade.js +711 -0
- package/scripts/flow-changelog +85 -0
- package/scripts/flow-checkpoint.js +483 -0
- package/scripts/flow-cli.js +403 -0
- package/scripts/flow-code-intelligence.js +760 -0
- package/scripts/flow-complexity.js +502 -0
- package/scripts/flow-config-set.js +152 -0
- package/scripts/flow-constants.js +157 -0
- package/scripts/flow-context +152 -0
- package/scripts/flow-context-init.js +482 -0
- package/scripts/flow-context-monitor.js +384 -0
- package/scripts/flow-context-scoring.js +886 -0
- package/scripts/flow-correct.js +458 -0
- package/scripts/flow-damage-control.js +985 -0
- package/scripts/flow-deps +101 -0
- package/scripts/flow-diff.js +700 -0
- package/scripts/flow-done +151 -0
- package/scripts/flow-done.js +489 -0
- package/scripts/flow-durable-session.js +1541 -0
- package/scripts/flow-entropy-monitor.js +345 -0
- package/scripts/flow-export-profile +349 -0
- package/scripts/flow-export-scanner.js +1046 -0
- package/scripts/flow-figma-confirm.js +400 -0
- package/scripts/flow-figma-extract.js +496 -0
- package/scripts/flow-figma-generate.js +683 -0
- package/scripts/flow-figma-index.js +909 -0
- package/scripts/flow-figma-match.js +617 -0
- package/scripts/flow-figma-mcp-server.js +518 -0
- package/scripts/flow-figma-pipeline.js +414 -0
- package/scripts/flow-file-ops.js +301 -0
- package/scripts/flow-gate-confidence.js +825 -0
- package/scripts/flow-guided-edit.js +659 -0
- package/scripts/flow-health +185 -0
- package/scripts/flow-health.js +413 -0
- package/scripts/flow-hooks.js +556 -0
- package/scripts/flow-http-client.js +249 -0
- package/scripts/flow-hybrid-detect.js +167 -0
- package/scripts/flow-hybrid-interactive.js +591 -0
- package/scripts/flow-hybrid-test.js +152 -0
- package/scripts/flow-import-profile +439 -0
- package/scripts/flow-init +253 -0
- package/scripts/flow-instruction-richness.js +827 -0
- package/scripts/flow-jira-integration.js +579 -0
- package/scripts/flow-knowledge-router.js +522 -0
- package/scripts/flow-knowledge-sync.js +589 -0
- package/scripts/flow-linear-integration.js +631 -0
- package/scripts/flow-links.js +774 -0
- package/scripts/flow-log-manager.js +559 -0
- package/scripts/flow-loop-enforcer.js +1246 -0
- package/scripts/flow-loop-retry-learning.js +630 -0
- package/scripts/flow-lsp.js +923 -0
- package/scripts/flow-map-index +348 -0
- package/scripts/flow-map-sync +201 -0
- package/scripts/flow-memory-blocks.js +668 -0
- package/scripts/flow-memory-compactor.js +350 -0
- package/scripts/flow-memory-db.js +1110 -0
- package/scripts/flow-memory-sync.js +484 -0
- package/scripts/flow-metrics.js +353 -0
- package/scripts/flow-migrate-ids.js +370 -0
- package/scripts/flow-model-adapter.js +802 -0
- package/scripts/flow-model-router.js +884 -0
- package/scripts/flow-models.js +1231 -0
- package/scripts/flow-morning.js +517 -0
- package/scripts/flow-multi-approach.js +660 -0
- package/scripts/flow-new-feature +86 -0
- package/scripts/flow-onboard +1042 -0
- package/scripts/flow-orchestrate-llm.js +459 -0
- package/scripts/flow-orchestrate.js +3592 -0
- package/scripts/flow-output.js +123 -0
- package/scripts/flow-parallel-detector.js +399 -0
- package/scripts/flow-parallel-dispatch.js +987 -0
- package/scripts/flow-parallel.js +428 -0
- package/scripts/flow-pattern-enforcer.js +600 -0
- package/scripts/flow-prd-manager.js +282 -0
- package/scripts/flow-progress.js +323 -0
- package/scripts/flow-project-analyzer.js +975 -0
- package/scripts/flow-prompt-composer.js +487 -0
- package/scripts/flow-providers.js +1381 -0
- package/scripts/flow-queue.js +308 -0
- package/scripts/flow-ready +82 -0
- package/scripts/flow-ready.js +189 -0
- package/scripts/flow-regression.js +396 -0
- package/scripts/flow-response-parser.js +450 -0
- package/scripts/flow-resume.js +284 -0
- package/scripts/flow-rules-sync.js +439 -0
- package/scripts/flow-run-trace.js +718 -0
- package/scripts/flow-safety.js +587 -0
- package/scripts/flow-search +104 -0
- package/scripts/flow-security.js +481 -0
- package/scripts/flow-session-end +106 -0
- package/scripts/flow-session-end.js +437 -0
- package/scripts/flow-session-state.js +671 -0
- package/scripts/flow-setup-hooks +216 -0
- package/scripts/flow-setup-hooks.js +377 -0
- package/scripts/flow-skill-create.js +329 -0
- package/scripts/flow-skill-creator.js +572 -0
- package/scripts/flow-skill-generator.js +1046 -0
- package/scripts/flow-skill-learn.js +880 -0
- package/scripts/flow-skill-matcher.js +578 -0
- package/scripts/flow-spec-generator.js +820 -0
- package/scripts/flow-stack-wizard.js +895 -0
- package/scripts/flow-standup +162 -0
- package/scripts/flow-start +74 -0
- package/scripts/flow-start.js +235 -0
- package/scripts/flow-status +110 -0
- package/scripts/flow-status.js +301 -0
- package/scripts/flow-step-browser.js +83 -0
- package/scripts/flow-step-changelog.js +217 -0
- package/scripts/flow-step-comments.js +306 -0
- package/scripts/flow-step-complexity.js +234 -0
- package/scripts/flow-step-coverage.js +218 -0
- package/scripts/flow-step-knowledge.js +193 -0
- package/scripts/flow-step-pr-tests.js +364 -0
- package/scripts/flow-step-regression.js +89 -0
- package/scripts/flow-step-review.js +516 -0
- package/scripts/flow-step-security.js +162 -0
- package/scripts/flow-step-silent-failures.js +290 -0
- package/scripts/flow-step-simplifier.js +346 -0
- package/scripts/flow-story +105 -0
- package/scripts/flow-story.js +500 -0
- package/scripts/flow-suspend.js +252 -0
- package/scripts/flow-sync-daemon.js +654 -0
- package/scripts/flow-task-analyzer.js +606 -0
- package/scripts/flow-team-dashboard.js +748 -0
- package/scripts/flow-team-sync.js +752 -0
- package/scripts/flow-team.js +977 -0
- package/scripts/flow-tech-options.js +528 -0
- package/scripts/flow-templates.js +812 -0
- package/scripts/flow-tiered-learning.js +728 -0
- package/scripts/flow-trace +204 -0
- package/scripts/flow-transcript-chunking.js +1106 -0
- package/scripts/flow-transcript-digest.js +7918 -0
- package/scripts/flow-transcript-language.js +465 -0
- package/scripts/flow-transcript-parsing.js +1085 -0
- package/scripts/flow-transcript-stories.js +2194 -0
- package/scripts/flow-update-map +224 -0
- package/scripts/flow-utils.js +2242 -0
- package/scripts/flow-verification.js +644 -0
- package/scripts/flow-verify.js +1177 -0
- package/scripts/flow-voice-input.js +638 -0
- package/scripts/flow-watch +168 -0
- package/scripts/flow-workflow-steps.js +521 -0
- package/scripts/flow-workflow.js +1029 -0
- package/scripts/flow-worktree.js +489 -0
- package/scripts/hooks/adapters/base-adapter.js +102 -0
- package/scripts/hooks/adapters/claude-code.js +359 -0
- package/scripts/hooks/adapters/index.js +79 -0
- package/scripts/hooks/core/component-check.js +341 -0
- package/scripts/hooks/core/index.js +35 -0
- package/scripts/hooks/core/loop-check.js +241 -0
- package/scripts/hooks/core/session-context.js +294 -0
- package/scripts/hooks/core/task-gate.js +177 -0
- package/scripts/hooks/core/validation.js +230 -0
- package/scripts/hooks/entry/claude-code/post-tool-use.js +65 -0
- package/scripts/hooks/entry/claude-code/pre-tool-use.js +89 -0
- package/scripts/hooks/entry/claude-code/session-end.js +87 -0
- package/scripts/hooks/entry/claude-code/session-start.js +46 -0
- package/scripts/hooks/entry/claude-code/stop.js +43 -0
- package/scripts/postinstall.js +139 -0
- package/templates/browser-test-flow.json +56 -0
- package/templates/bug-report.md +43 -0
- package/templates/component-detail.md +42 -0
- package/templates/component.stories.tsx +49 -0
- package/templates/context/constraints.md +83 -0
- package/templates/context/conventions.md +177 -0
- package/templates/context/stack.md +60 -0
- package/templates/correction-report.md +90 -0
- package/templates/feature-proposal.md +35 -0
- package/templates/hybrid/_base.md +254 -0
- package/templates/hybrid/_patterns.md +45 -0
- package/templates/hybrid/create-component.md +127 -0
- package/templates/hybrid/create-file.md +56 -0
- package/templates/hybrid/create-hook.md +145 -0
- package/templates/hybrid/create-service.md +70 -0
- package/templates/hybrid/fix-bug.md +33 -0
- package/templates/hybrid/modify-file.md +55 -0
- package/templates/story.md +68 -0
- package/templates/task.json +56 -0
- package/templates/trace.md +69 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Wogi Flow - Claude Code PostToolUse Hook
|
|
5
|
+
*
|
|
6
|
+
* Called after Edit/Write tool execution.
|
|
7
|
+
* Runs validation (lint, typecheck) on modified files.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const { runValidation } = require('../../core/validation');
|
|
11
|
+
const { claudeCodeAdapter } = require('../../adapters/claude-code');
|
|
12
|
+
|
|
13
|
+
async function main() {
|
|
14
|
+
try {
|
|
15
|
+
// Read input from stdin
|
|
16
|
+
let inputData = '';
|
|
17
|
+
for await (const chunk of process.stdin) {
|
|
18
|
+
inputData += chunk;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const input = inputData ? JSON.parse(inputData) : {};
|
|
22
|
+
const parsedInput = claudeCodeAdapter.parseInput(input);
|
|
23
|
+
|
|
24
|
+
const toolName = parsedInput.toolName;
|
|
25
|
+
const toolInput = parsedInput.toolInput || {};
|
|
26
|
+
const toolResponse = parsedInput.toolResponse;
|
|
27
|
+
const filePath = toolInput.file_path;
|
|
28
|
+
|
|
29
|
+
// Only run validation for Edit/Write
|
|
30
|
+
if (toolName !== 'Edit' && toolName !== 'Write') {
|
|
31
|
+
console.log(JSON.stringify({ continue: true }));
|
|
32
|
+
process.exit(0);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Skip if tool failed
|
|
37
|
+
if (toolResponse && toolResponse.error) {
|
|
38
|
+
console.log(JSON.stringify({ continue: true }));
|
|
39
|
+
process.exit(0);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Run validation
|
|
44
|
+
const coreResult = await runValidation({
|
|
45
|
+
filePath,
|
|
46
|
+
timeout: 30000
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// Transform to Claude Code format
|
|
50
|
+
const output = claudeCodeAdapter.transformResult('PostToolUse', coreResult);
|
|
51
|
+
|
|
52
|
+
// Output JSON
|
|
53
|
+
console.log(JSON.stringify(output));
|
|
54
|
+
process.exit(0);
|
|
55
|
+
} catch (err) {
|
|
56
|
+
// Non-blocking error
|
|
57
|
+
console.error(`[Wogi Flow Hook Error] ${err.message}`);
|
|
58
|
+
console.log(JSON.stringify({ continue: true }));
|
|
59
|
+
process.exit(0);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Handle stdin properly
|
|
64
|
+
process.stdin.setEncoding('utf8');
|
|
65
|
+
main();
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Wogi Flow - Claude Code PreToolUse Hook
|
|
5
|
+
*
|
|
6
|
+
* Called before Edit/Write tool execution.
|
|
7
|
+
* Enforces task gating and component reuse checking.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const { checkTaskGate } = require('../../core/task-gate');
|
|
11
|
+
const { checkComponentReuse } = require('../../core/component-check');
|
|
12
|
+
const { claudeCodeAdapter } = require('../../adapters/claude-code');
|
|
13
|
+
|
|
14
|
+
async function main() {
|
|
15
|
+
try {
|
|
16
|
+
// Read input from stdin
|
|
17
|
+
let inputData = '';
|
|
18
|
+
for await (const chunk of process.stdin) {
|
|
19
|
+
inputData += chunk;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const input = inputData ? JSON.parse(inputData) : {};
|
|
23
|
+
const parsedInput = claudeCodeAdapter.parseInput(input);
|
|
24
|
+
|
|
25
|
+
const toolName = parsedInput.toolName;
|
|
26
|
+
const toolInput = parsedInput.toolInput || {};
|
|
27
|
+
const filePath = toolInput.file_path;
|
|
28
|
+
|
|
29
|
+
let coreResult = { allowed: true, blocked: false };
|
|
30
|
+
|
|
31
|
+
// Task gating check (for Edit and Write)
|
|
32
|
+
if (toolName === 'Edit' || toolName === 'Write') {
|
|
33
|
+
coreResult = checkTaskGate({
|
|
34
|
+
filePath,
|
|
35
|
+
operation: toolName.toLowerCase()
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// If blocked by task gating, return early
|
|
39
|
+
if (coreResult.blocked) {
|
|
40
|
+
const output = claudeCodeAdapter.transformResult('PreToolUse', coreResult);
|
|
41
|
+
console.log(JSON.stringify(output));
|
|
42
|
+
process.exit(0);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Component reuse check (for Write only)
|
|
48
|
+
if (toolName === 'Write' && filePath) {
|
|
49
|
+
const componentResult = checkComponentReuse({
|
|
50
|
+
filePath,
|
|
51
|
+
content: toolInput.content
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Merge results - component check can add warning or block
|
|
55
|
+
if (componentResult.blocked || componentResult.warning) {
|
|
56
|
+
coreResult = {
|
|
57
|
+
...coreResult,
|
|
58
|
+
...componentResult,
|
|
59
|
+
// Preserve task gating allowance unless component check blocks
|
|
60
|
+
allowed: !componentResult.blocked,
|
|
61
|
+
blocked: componentResult.blocked
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Transform to Claude Code format
|
|
67
|
+
const output = claudeCodeAdapter.transformResult('PreToolUse', coreResult);
|
|
68
|
+
|
|
69
|
+
// Output JSON
|
|
70
|
+
console.log(JSON.stringify(output));
|
|
71
|
+
process.exit(0);
|
|
72
|
+
} catch (err) {
|
|
73
|
+
// Non-blocking error - allow operation to continue
|
|
74
|
+
console.error(`[Wogi Flow Hook Error] ${err.message}`);
|
|
75
|
+
// Exit 0 with allow to not block on hook errors (graceful degradation)
|
|
76
|
+
console.log(JSON.stringify({
|
|
77
|
+
continue: true,
|
|
78
|
+
hookSpecificOutput: {
|
|
79
|
+
hookEventName: 'PreToolUse',
|
|
80
|
+
permissionDecision: 'allow'
|
|
81
|
+
}
|
|
82
|
+
}));
|
|
83
|
+
process.exit(0);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Handle stdin properly
|
|
88
|
+
process.stdin.setEncoding('utf8');
|
|
89
|
+
main();
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Wogi Flow - Claude Code SessionEnd Hook
|
|
5
|
+
*
|
|
6
|
+
* Called when a Claude Code session ends.
|
|
7
|
+
* Auto-logs to request-log.md and warns about uncommitted work.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
const { execSync } = require('child_process');
|
|
13
|
+
const { claudeCodeAdapter } = require('../../adapters/claude-code');
|
|
14
|
+
|
|
15
|
+
// Import from parent scripts directory
|
|
16
|
+
const { getConfig, PATHS } = require('../../../flow-utils');
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Get uncommitted file count
|
|
20
|
+
*/
|
|
21
|
+
function getUncommittedCount() {
|
|
22
|
+
try {
|
|
23
|
+
const output = execSync('git status --porcelain', {
|
|
24
|
+
cwd: PATHS.root,
|
|
25
|
+
encoding: 'utf-8',
|
|
26
|
+
stdio: ['pipe', 'pipe', 'pipe']
|
|
27
|
+
});
|
|
28
|
+
return output.trim().split('\n').filter(line => line.trim()).length;
|
|
29
|
+
} catch {
|
|
30
|
+
return 0;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Check if auto-logging is enabled
|
|
36
|
+
*/
|
|
37
|
+
function isAutoLoggingEnabled() {
|
|
38
|
+
const config = getConfig();
|
|
39
|
+
return config.hooks?.rules?.autoLogging?.enabled !== false;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async function main() {
|
|
43
|
+
try {
|
|
44
|
+
// Read input from stdin
|
|
45
|
+
let inputData = '';
|
|
46
|
+
for await (const chunk of process.stdin) {
|
|
47
|
+
inputData += chunk;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const input = inputData ? JSON.parse(inputData) : {};
|
|
51
|
+
const parsedInput = claudeCodeAdapter.parseInput(input);
|
|
52
|
+
|
|
53
|
+
const result = {
|
|
54
|
+
logged: false,
|
|
55
|
+
warning: null
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// Check for uncommitted work
|
|
59
|
+
const uncommitted = getUncommittedCount();
|
|
60
|
+
if (uncommitted > 0) {
|
|
61
|
+
result.warning = `${uncommitted} uncommitted file${uncommitted !== 1 ? 's' : ''}. Consider committing before ending session.`;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Auto-logging would go here but requires more session context
|
|
65
|
+
// For now, just warn about uncommitted work
|
|
66
|
+
if (isAutoLoggingEnabled()) {
|
|
67
|
+
// Could integrate with flow-session-end.js in the future
|
|
68
|
+
result.logged = false;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Transform to Claude Code format
|
|
72
|
+
const output = claudeCodeAdapter.transformResult('SessionEnd', result);
|
|
73
|
+
|
|
74
|
+
// Output JSON
|
|
75
|
+
console.log(JSON.stringify(output));
|
|
76
|
+
process.exit(0);
|
|
77
|
+
} catch (err) {
|
|
78
|
+
// Non-blocking error
|
|
79
|
+
console.error(`[Wogi Flow Hook Error] ${err.message}`);
|
|
80
|
+
console.log(JSON.stringify({ continue: true }));
|
|
81
|
+
process.exit(0);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Handle stdin properly
|
|
86
|
+
process.stdin.setEncoding('utf8');
|
|
87
|
+
main();
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Wogi Flow - Claude Code SessionStart Hook
|
|
5
|
+
*
|
|
6
|
+
* Called when a Claude Code session starts.
|
|
7
|
+
* Injects context (suspended tasks, decisions, recent activity).
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const { gatherSessionContext } = require('../../core/session-context');
|
|
11
|
+
const { claudeCodeAdapter } = require('../../adapters/claude-code');
|
|
12
|
+
|
|
13
|
+
async function main() {
|
|
14
|
+
try {
|
|
15
|
+
// Read input from stdin
|
|
16
|
+
let inputData = '';
|
|
17
|
+
for await (const chunk of process.stdin) {
|
|
18
|
+
inputData += chunk;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const input = inputData ? JSON.parse(inputData) : {};
|
|
22
|
+
const parsedInput = claudeCodeAdapter.parseInput(input);
|
|
23
|
+
|
|
24
|
+
// Gather session context
|
|
25
|
+
const coreResult = gatherSessionContext({
|
|
26
|
+
includeSuspended: true,
|
|
27
|
+
includeDecisions: true,
|
|
28
|
+
includeActivity: true
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// Transform to Claude Code format
|
|
32
|
+
const output = claudeCodeAdapter.transformResult('SessionStart', coreResult);
|
|
33
|
+
|
|
34
|
+
// Output JSON
|
|
35
|
+
console.log(JSON.stringify(output));
|
|
36
|
+
process.exit(0);
|
|
37
|
+
} catch (err) {
|
|
38
|
+
// Non-blocking error - log to stderr, exit 1
|
|
39
|
+
console.error(`[Wogi Flow Hook Error] ${err.message}`);
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Handle stdin properly
|
|
45
|
+
process.stdin.setEncoding('utf8');
|
|
46
|
+
main();
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Wogi Flow - Claude Code Stop Hook
|
|
5
|
+
*
|
|
6
|
+
* Called when Claude is about to stop.
|
|
7
|
+
* Enforces loop completion - blocks stop if acceptance criteria incomplete.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const { checkLoopExit } = require('../../core/loop-check');
|
|
11
|
+
const { claudeCodeAdapter } = require('../../adapters/claude-code');
|
|
12
|
+
|
|
13
|
+
async function main() {
|
|
14
|
+
try {
|
|
15
|
+
// Read input from stdin
|
|
16
|
+
let inputData = '';
|
|
17
|
+
for await (const chunk of process.stdin) {
|
|
18
|
+
inputData += chunk;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const input = inputData ? JSON.parse(inputData) : {};
|
|
22
|
+
const parsedInput = claudeCodeAdapter.parseInput(input);
|
|
23
|
+
|
|
24
|
+
// Check if loop can exit
|
|
25
|
+
const coreResult = checkLoopExit();
|
|
26
|
+
|
|
27
|
+
// Transform to Claude Code format
|
|
28
|
+
const output = claudeCodeAdapter.transformResult('Stop', coreResult);
|
|
29
|
+
|
|
30
|
+
// Output JSON
|
|
31
|
+
console.log(JSON.stringify(output));
|
|
32
|
+
process.exit(0);
|
|
33
|
+
} catch (err) {
|
|
34
|
+
// On error, allow stop (don't block user)
|
|
35
|
+
console.error(`[Wogi Flow Hook Error] ${err.message}`);
|
|
36
|
+
console.log(JSON.stringify({ continue: false })); // Allow stop
|
|
37
|
+
process.exit(0);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Handle stdin properly
|
|
42
|
+
process.stdin.setEncoding('utf8');
|
|
43
|
+
main();
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* WogiFlow postinstall script
|
|
5
|
+
*
|
|
6
|
+
* Runs after npm install to set up project structure.
|
|
7
|
+
* Creates necessary directories and copies template files for fresh installs.
|
|
8
|
+
* Preserves existing user data (never overwrites).
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
|
|
14
|
+
// Directory structure
|
|
15
|
+
const WORKFLOW_DIR = '.workflow';
|
|
16
|
+
const STATE_DIR = path.join(WORKFLOW_DIR, 'state');
|
|
17
|
+
const CHANGES_DIR = path.join(WORKFLOW_DIR, 'changes');
|
|
18
|
+
const MEMORY_DIR = path.join(WORKFLOW_DIR, 'memory');
|
|
19
|
+
const VERIFICATIONS_DIR = path.join(WORKFLOW_DIR, 'verifications');
|
|
20
|
+
const SPECS_DIR = path.join(WORKFLOW_DIR, 'specs');
|
|
21
|
+
|
|
22
|
+
// Find template directory (relative to this script's location in node_modules)
|
|
23
|
+
function findTemplateDir() {
|
|
24
|
+
// When installed via npm, templates are in the package
|
|
25
|
+
const npmPath = path.join(__dirname, '..', '.workflow', 'state');
|
|
26
|
+
if (fs.existsSync(npmPath)) {
|
|
27
|
+
return npmPath;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Fallback for local development
|
|
31
|
+
const localPath = path.join(process.cwd(), '.workflow', 'state');
|
|
32
|
+
if (fs.existsSync(localPath)) {
|
|
33
|
+
return localPath;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Template files to copy (without .template extension in target)
|
|
40
|
+
const TEMPLATES = [
|
|
41
|
+
'ready.json',
|
|
42
|
+
'request-log.md',
|
|
43
|
+
'progress.md',
|
|
44
|
+
'app-map.md',
|
|
45
|
+
'decisions.md',
|
|
46
|
+
'component-index.json',
|
|
47
|
+
'feedback-patterns.md',
|
|
48
|
+
'architecture.md',
|
|
49
|
+
'stack.md',
|
|
50
|
+
'testing.md',
|
|
51
|
+
'session-state.json',
|
|
52
|
+
'knowledge-sync.json'
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
function ensureDir(dir) {
|
|
56
|
+
if (!fs.existsSync(dir)) {
|
|
57
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function createGitkeep(dir) {
|
|
64
|
+
const gitkeepPath = path.join(dir, '.gitkeep');
|
|
65
|
+
if (!fs.existsSync(gitkeepPath)) {
|
|
66
|
+
fs.writeFileSync(gitkeepPath, '');
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function copyTemplates(templateDir) {
|
|
71
|
+
let copied = 0;
|
|
72
|
+
|
|
73
|
+
for (const file of TEMPLATES) {
|
|
74
|
+
const templatePath = path.join(templateDir, `${file}.template`);
|
|
75
|
+
const targetPath = path.join(STATE_DIR, file);
|
|
76
|
+
|
|
77
|
+
// Only copy if target doesn't exist (preserve user data)
|
|
78
|
+
if (!fs.existsSync(targetPath) && fs.existsSync(templatePath)) {
|
|
79
|
+
try {
|
|
80
|
+
fs.copyFileSync(templatePath, targetPath);
|
|
81
|
+
console.log(` \x1b[32m✓\x1b[0m Created ${file}`);
|
|
82
|
+
copied++;
|
|
83
|
+
} catch (err) {
|
|
84
|
+
console.log(` \x1b[33m!\x1b[0m Could not create ${file}: ${err.message}`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return copied;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function main() {
|
|
93
|
+
// Skip if running in CI or non-interactive environment
|
|
94
|
+
if (process.env.CI || process.env.WOGIFLOW_SKIP_POSTINSTALL) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
console.log('\n\x1b[36mWogiFlow\x1b[0m: Setting up project structure...\n');
|
|
99
|
+
|
|
100
|
+
// Create directory structure
|
|
101
|
+
const dirsCreated = [];
|
|
102
|
+
|
|
103
|
+
if (ensureDir(WORKFLOW_DIR)) dirsCreated.push(WORKFLOW_DIR);
|
|
104
|
+
if (ensureDir(STATE_DIR)) dirsCreated.push(STATE_DIR);
|
|
105
|
+
if (ensureDir(CHANGES_DIR)) dirsCreated.push(CHANGES_DIR);
|
|
106
|
+
if (ensureDir(MEMORY_DIR)) dirsCreated.push(MEMORY_DIR);
|
|
107
|
+
if (ensureDir(VERIFICATIONS_DIR)) dirsCreated.push(VERIFICATIONS_DIR);
|
|
108
|
+
if (ensureDir(SPECS_DIR)) dirsCreated.push(SPECS_DIR);
|
|
109
|
+
|
|
110
|
+
// Create .gitkeep files to preserve empty directories
|
|
111
|
+
createGitkeep(CHANGES_DIR);
|
|
112
|
+
createGitkeep(VERIFICATIONS_DIR);
|
|
113
|
+
createGitkeep(SPECS_DIR);
|
|
114
|
+
|
|
115
|
+
if (dirsCreated.length > 0) {
|
|
116
|
+
console.log(` \x1b[32m✓\x1b[0m Created directories: ${dirsCreated.join(', ')}`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Find and copy templates
|
|
120
|
+
const templateDir = findTemplateDir();
|
|
121
|
+
|
|
122
|
+
if (templateDir) {
|
|
123
|
+
const copied = copyTemplates(templateDir);
|
|
124
|
+
if (copied > 0) {
|
|
125
|
+
console.log(`\n \x1b[32m✓\x1b[0m Initialized ${copied} state files from templates`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
console.log('\n\x1b[36mWogiFlow\x1b[0m: Setup complete!');
|
|
130
|
+
console.log(' Run \x1b[33mflow onboard\x1b[0m to analyze your project.\n');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Run
|
|
134
|
+
try {
|
|
135
|
+
main();
|
|
136
|
+
} catch (err) {
|
|
137
|
+
// Don't fail install on postinstall errors
|
|
138
|
+
console.log(`\x1b[33mWogiFlow postinstall warning:\x1b[0m ${err.message}`);
|
|
139
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "[flow-name]",
|
|
3
|
+
"description": "[What this flow tests]",
|
|
4
|
+
"created": "[date]",
|
|
5
|
+
"tags": ["#e2e", "#screen:[name]"],
|
|
6
|
+
"baseUrl": "http://localhost:3000",
|
|
7
|
+
"steps": [
|
|
8
|
+
{
|
|
9
|
+
"action": "navigate",
|
|
10
|
+
"url": "/path",
|
|
11
|
+
"description": "Go to the target page"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"action": "wait",
|
|
15
|
+
"selector": ".page-loaded",
|
|
16
|
+
"timeout": 5000,
|
|
17
|
+
"description": "Wait for page to load"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"action": "type",
|
|
21
|
+
"selector": "#email",
|
|
22
|
+
"value": "test@example.com",
|
|
23
|
+
"description": "Enter email address"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"action": "type",
|
|
27
|
+
"selector": "#password",
|
|
28
|
+
"value": "password123",
|
|
29
|
+
"description": "Enter password"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"action": "click",
|
|
33
|
+
"selector": "button[type=submit]",
|
|
34
|
+
"description": "Submit the form"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"action": "verify",
|
|
38
|
+
"selector": ".dashboard",
|
|
39
|
+
"exists": true,
|
|
40
|
+
"description": "Verify dashboard is visible"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"action": "verify",
|
|
44
|
+
"selector": ".welcome-message",
|
|
45
|
+
"contains": "Welcome",
|
|
46
|
+
"description": "Verify welcome message"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"action": "screenshot",
|
|
50
|
+
"name": "dashboard-loaded",
|
|
51
|
+
"description": "Capture final state"
|
|
52
|
+
}
|
|
53
|
+
],
|
|
54
|
+
"expectedResult": "[What should happen when flow completes]",
|
|
55
|
+
"relatedStory": "TASK-XXX"
|
|
56
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# wf-XXXXXXXX: [Title]
|
|
2
|
+
|
|
3
|
+
**Created**: [date]
|
|
4
|
+
**Status**: Open / In Progress / Fixed / Closed
|
|
5
|
+
**Severity**: Critical / High / Medium / Low
|
|
6
|
+
**Priority**: P0-P4
|
|
7
|
+
**Tags**: #bug #component:[name] #screen:[name]
|
|
8
|
+
**Discovered From**: [wf-XXXXXXXX or empty if not during task]
|
|
9
|
+
**Discovered During**: implementation / testing / review
|
|
10
|
+
|
|
11
|
+
## Description
|
|
12
|
+
[Clear description of the bug]
|
|
13
|
+
|
|
14
|
+
## Steps to Reproduce
|
|
15
|
+
1. [Step 1]
|
|
16
|
+
2. [Step 2]
|
|
17
|
+
3. [Step 3]
|
|
18
|
+
|
|
19
|
+
## Expected Behavior
|
|
20
|
+
[What should happen]
|
|
21
|
+
|
|
22
|
+
## Actual Behavior
|
|
23
|
+
[What actually happens]
|
|
24
|
+
|
|
25
|
+
## Environment
|
|
26
|
+
- Browser:
|
|
27
|
+
- OS:
|
|
28
|
+
- Version:
|
|
29
|
+
|
|
30
|
+
## Screenshots
|
|
31
|
+
[If applicable]
|
|
32
|
+
|
|
33
|
+
## Possible Fix
|
|
34
|
+
[If you have ideas about what's causing it or how to fix]
|
|
35
|
+
|
|
36
|
+
## Related
|
|
37
|
+
- [Related request-log entries]
|
|
38
|
+
- [Related components from app-map]
|
|
39
|
+
|
|
40
|
+
## Resolution
|
|
41
|
+
[Fill in when fixed]
|
|
42
|
+
- Fixed in: [commit/PR]
|
|
43
|
+
- Root cause: [explanation]
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# [Component Name]
|
|
2
|
+
|
|
3
|
+
**Path**: `src/components/[path]`
|
|
4
|
+
**Status**: complete | in-progress | planned
|
|
5
|
+
|
|
6
|
+
## Variants
|
|
7
|
+
|
|
8
|
+
| Variant | Description |
|
|
9
|
+
|---------|-------------|
|
|
10
|
+
| `primary` | Main action style |
|
|
11
|
+
| `secondary` | Secondary action style |
|
|
12
|
+
|
|
13
|
+
## Props
|
|
14
|
+
|
|
15
|
+
| Prop | Type | Required | Default | Description |
|
|
16
|
+
|------|------|----------|---------|-------------|
|
|
17
|
+
| `variant` | string | no | `primary` | Visual style |
|
|
18
|
+
| `size` | `sm` \| `md` \| `lg` | no | `md` | Component size |
|
|
19
|
+
| `disabled` | boolean | no | `false` | Disabled state |
|
|
20
|
+
| `onClick` | function | no | - | Click handler |
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
import { ComponentName } from '@/components/[path]'
|
|
26
|
+
|
|
27
|
+
<ComponentName variant="primary" size="lg">
|
|
28
|
+
Label
|
|
29
|
+
</ComponentName>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Used In
|
|
33
|
+
|
|
34
|
+
- ScreenName
|
|
35
|
+
- ModalName
|
|
36
|
+
- OtherComponent
|
|
37
|
+
|
|
38
|
+
## Notes
|
|
39
|
+
|
|
40
|
+
- Any special behaviors or gotchas
|
|
41
|
+
- Performance considerations
|
|
42
|
+
- Accessibility notes
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { [ComponentName] } from './[ComponentName]';
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof [ComponentName]> = {
|
|
5
|
+
title: 'Components/[ComponentName]',
|
|
6
|
+
component: [ComponentName],
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: 'centered',
|
|
9
|
+
},
|
|
10
|
+
tags: ['autodocs'],
|
|
11
|
+
argTypes: {
|
|
12
|
+
// Add argTypes based on props
|
|
13
|
+
// variant: {
|
|
14
|
+
// control: 'select',
|
|
15
|
+
// options: ['primary', 'secondary'],
|
|
16
|
+
// },
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default meta;
|
|
21
|
+
type Story = StoryObj<typeof meta>;
|
|
22
|
+
|
|
23
|
+
// Default story
|
|
24
|
+
export const Default: Story = {
|
|
25
|
+
args: {
|
|
26
|
+
// Add default props
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// Variant stories
|
|
31
|
+
// export const Primary: Story = {
|
|
32
|
+
// args: {
|
|
33
|
+
// variant: 'primary',
|
|
34
|
+
// },
|
|
35
|
+
// };
|
|
36
|
+
|
|
37
|
+
// export const Secondary: Story = {
|
|
38
|
+
// args: {
|
|
39
|
+
// variant: 'secondary',
|
|
40
|
+
// },
|
|
41
|
+
// };
|
|
42
|
+
|
|
43
|
+
// Interactive story
|
|
44
|
+
// export const Interactive: Story = {
|
|
45
|
+
// args: {},
|
|
46
|
+
// play: async ({ canvasElement }) => {
|
|
47
|
+
// // Add interaction tests
|
|
48
|
+
// },
|
|
49
|
+
// };
|