@dv.nghiem/flowdeck 0.1.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/LICENSE +21 -0
- package/README.md +136 -0
- package/bin/flowdeck.js +108 -0
- package/dist/agents/architect.d.ts +3 -0
- package/dist/agents/architect.d.ts.map +1 -0
- package/dist/agents/code-explorer.d.ts +3 -0
- package/dist/agents/code-explorer.d.ts.map +1 -0
- package/dist/agents/coder.d.ts +3 -0
- package/dist/agents/coder.d.ts.map +1 -0
- package/dist/agents/debug.d.ts +4 -0
- package/dist/agents/debug.d.ts.map +1 -0
- package/dist/agents/doc-updater.d.ts +3 -0
- package/dist/agents/doc-updater.d.ts.map +1 -0
- package/dist/agents/flowdeck.d.ts +5 -0
- package/dist/agents/flowdeck.d.ts.map +1 -0
- package/dist/agents/index.d.ts +38 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/mapper.d.ts +3 -0
- package/dist/agents/mapper.d.ts.map +1 -0
- package/dist/agents/orchestrator.d.ts +10 -0
- package/dist/agents/orchestrator.d.ts.map +1 -0
- package/dist/agents/performance.d.ts +4 -0
- package/dist/agents/performance.d.ts.map +1 -0
- package/dist/agents/planner.d.ts +3 -0
- package/dist/agents/planner.d.ts.map +1 -0
- package/dist/agents/policy-enforcer.d.ts +3 -0
- package/dist/agents/policy-enforcer.d.ts.map +1 -0
- package/dist/agents/researcher.d.ts +3 -0
- package/dist/agents/researcher.d.ts.map +1 -0
- package/dist/agents/reviewer.d.ts +3 -0
- package/dist/agents/reviewer.d.ts.map +1 -0
- package/dist/agents/risk-analyst.d.ts +3 -0
- package/dist/agents/risk-analyst.d.ts.map +1 -0
- package/dist/agents/security-auditor.d.ts +3 -0
- package/dist/agents/security-auditor.d.ts.map +1 -0
- package/dist/agents/specialist.d.ts +5 -0
- package/dist/agents/specialist.d.ts.map +1 -0
- package/dist/agents/tester.d.ts +3 -0
- package/dist/agents/tester.d.ts.map +1 -0
- package/dist/agents/types.d.ts +20 -0
- package/dist/agents/types.d.ts.map +1 -0
- package/dist/agents/writer.d.ts +3 -0
- package/dist/agents/writer.d.ts.map +1 -0
- package/dist/commands/analysis/analysis.test.d.ts +2 -0
- package/dist/commands/analysis/analysis.test.d.ts.map +1 -0
- package/dist/commands/analysis/analyze-change.d.ts +148 -0
- package/dist/commands/analysis/analyze-change.d.ts.map +1 -0
- package/dist/commands/analysis/evaluate-risk.d.ts +77 -0
- package/dist/commands/analysis/evaluate-risk.d.ts.map +1 -0
- package/dist/commands/analysis/guarded-edit.d.ts +72 -0
- package/dist/commands/analysis/guarded-edit.d.ts.map +1 -0
- package/dist/commands/execution/deploy-check.d.ts +91 -0
- package/dist/commands/execution/deploy-check.d.ts.map +1 -0
- package/dist/commands/execution/fix-bug.d.ts +187 -0
- package/dist/commands/execution/fix-bug.d.ts.map +1 -0
- package/dist/commands/execution/new-feature.d.ts +171 -0
- package/dist/commands/execution/new-feature.d.ts.map +1 -0
- package/dist/commands/execution/review-code.d.ts +130 -0
- package/dist/commands/execution/review-code.d.ts.map +1 -0
- package/dist/commands/execution/write-docs.d.ts +94 -0
- package/dist/commands/execution/write-docs.d.ts.map +1 -0
- package/dist/commands/governance/approve.d.ts +80 -0
- package/dist/commands/governance/approve.d.ts.map +1 -0
- package/dist/commands/intelligence/blast-radius.d.ts +67 -0
- package/dist/commands/intelligence/blast-radius.d.ts.map +1 -0
- package/dist/commands/intelligence/impact-radar.d.ts +71 -0
- package/dist/commands/intelligence/impact-radar.d.ts.map +1 -0
- package/dist/commands/intelligence/intelligence.test.d.ts +2 -0
- package/dist/commands/intelligence/intelligence.test.d.ts.map +1 -0
- package/dist/commands/intelligence/regression-predict.d.ts +75 -0
- package/dist/commands/intelligence/regression-predict.d.ts.map +1 -0
- package/dist/commands/intelligence/review-route.d.ts +65 -0
- package/dist/commands/intelligence/review-route.d.ts.map +1 -0
- package/dist/commands/intelligence/test-gap.d.ts +73 -0
- package/dist/commands/intelligence/test-gap.d.ts.map +1 -0
- package/dist/commands/intelligence/translate-intent.d.ts +87 -0
- package/dist/commands/intelligence/translate-intent.d.ts.map +1 -0
- package/dist/commands/intelligence/volatility-map-cmd.d.ts +68 -0
- package/dist/commands/intelligence/volatility-map-cmd.d.ts.map +1 -0
- package/dist/commands/planning/ask.d.ts +62 -0
- package/dist/commands/planning/ask.d.ts.map +1 -0
- package/dist/commands/planning/ask.test.d.ts +2 -0
- package/dist/commands/planning/ask.test.d.ts.map +1 -0
- package/dist/commands/planning/dashboard.d.ts +30 -0
- package/dist/commands/planning/dashboard.d.ts.map +1 -0
- package/dist/commands/planning/discuss.d.ts +39 -0
- package/dist/commands/planning/discuss.d.ts.map +1 -0
- package/dist/commands/planning/plan.d.ts +67 -0
- package/dist/commands/planning/plan.d.ts.map +1 -0
- package/dist/commands/planning/roadmap.d.ts +105 -0
- package/dist/commands/planning/roadmap.d.ts.map +1 -0
- package/dist/commands/setup/doctor.d.ts +10 -0
- package/dist/commands/setup/doctor.d.ts.map +1 -0
- package/dist/commands/setup/map-codebase.d.ts +62 -0
- package/dist/commands/setup/map-codebase.d.ts.map +1 -0
- package/dist/commands/setup/new-project.d.ts +19 -0
- package/dist/commands/setup/new-project.d.ts.map +1 -0
- package/dist/commands/setup/settings.d.ts +57 -0
- package/dist/commands/setup/settings.d.ts.map +1 -0
- package/dist/commands/state/checkpoint.d.ts +27 -0
- package/dist/commands/state/checkpoint.d.ts.map +1 -0
- package/dist/commands/state/multi-repo.d.ts +63 -0
- package/dist/commands/state/multi-repo.d.ts.map +1 -0
- package/dist/commands/state/progress.d.ts +57 -0
- package/dist/commands/state/progress.d.ts.map +1 -0
- package/dist/commands/state/resume.d.ts +11 -0
- package/dist/commands/state/resume.d.ts.map +1 -0
- package/dist/commands/state/workspace-commands.d.ts +207 -0
- package/dist/commands/state/workspace-commands.d.ts.map +1 -0
- package/dist/dashboard/lib/port-finder.d.ts +10 -0
- package/dist/dashboard/lib/port-finder.d.ts.map +1 -0
- package/dist/dashboard/lib/port-finder.test.d.ts +2 -0
- package/dist/dashboard/lib/port-finder.test.d.ts.map +1 -0
- package/dist/dashboard/lib/state-reader.d.ts +3 -0
- package/dist/dashboard/lib/state-reader.d.ts.map +1 -0
- package/dist/dashboard/server.d.ts +2 -0
- package/dist/dashboard/server.d.ts.map +1 -0
- package/dist/dashboard/server.mjs +13649 -0
- package/dist/dashboard/types.d.ts +72 -0
- package/dist/dashboard/types.d.ts.map +1 -0
- package/dist/dashboard/views/index.ejs +391 -0
- package/dist/dashboard/views/partials/blockers.ejs +10 -0
- package/dist/dashboard/views/partials/header.ejs +20 -0
- package/dist/dashboard/views/partials/phase-timeline.ejs +40 -0
- package/dist/dashboard/views/partials/progress.ejs +12 -0
- package/dist/hooks/approval-hook.d.ts +13 -0
- package/dist/hooks/approval-hook.d.ts.map +1 -0
- package/dist/hooks/compaction-hook.d.ts +23 -0
- package/dist/hooks/compaction-hook.d.ts.map +1 -0
- package/dist/hooks/context-window-monitor.d.ts +21 -0
- package/dist/hooks/context-window-monitor.d.ts.map +1 -0
- package/dist/hooks/decision-trace-hook.d.ts +13 -0
- package/dist/hooks/decision-trace-hook.d.ts.map +1 -0
- package/dist/hooks/file-tracker.d.ts +29 -0
- package/dist/hooks/file-tracker.d.ts.map +1 -0
- package/dist/hooks/guard-rails.d.ts +33 -0
- package/dist/hooks/guard-rails.d.ts.map +1 -0
- package/dist/hooks/index.d.ts +5 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/notifications.d.ts +21 -0
- package/dist/hooks/notifications.d.ts.map +1 -0
- package/dist/hooks/patch-trust.d.ts +27 -0
- package/dist/hooks/patch-trust.d.ts.map +1 -0
- package/dist/hooks/patch-trust.test.d.ts +2 -0
- package/dist/hooks/patch-trust.test.d.ts.map +1 -0
- package/dist/hooks/session-events.d.ts +8 -0
- package/dist/hooks/session-events.d.ts.map +1 -0
- package/dist/hooks/session-idle-hook.d.ts +21 -0
- package/dist/hooks/session-idle-hook.d.ts.map +1 -0
- package/dist/hooks/session-start.d.ts +10 -0
- package/dist/hooks/session-start.d.ts.map +1 -0
- package/dist/hooks/shell-env-hook.d.ts +21 -0
- package/dist/hooks/shell-env-hook.d.ts.map +1 -0
- package/dist/hooks/telemetry-hook.d.ts +25 -0
- package/dist/hooks/telemetry-hook.d.ts.map +1 -0
- package/dist/hooks/todo-hook.d.ts +25 -0
- package/dist/hooks/todo-hook.d.ts.map +1 -0
- package/dist/hooks/tool-guard.d.ts +41 -0
- package/dist/hooks/tool-guard.d.ts.map +1 -0
- package/dist/hooks/tool-guard.test.d.ts +2 -0
- package/dist/hooks/tool-guard.test.d.ts.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6639 -0
- package/dist/lib/confirmation.d.ts +20 -0
- package/dist/lib/confirmation.d.ts.map +1 -0
- package/dist/lib/impact-radar.d.ts +35 -0
- package/dist/lib/impact-radar.d.ts.map +1 -0
- package/dist/lib/signatures.d.ts +12 -0
- package/dist/lib/signatures.d.ts.map +1 -0
- package/dist/lib/timestamps.d.ts +23 -0
- package/dist/lib/timestamps.d.ts.map +1 -0
- package/dist/mcp/index.d.ts +20 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/services/agent-performance.d.ts +29 -0
- package/dist/services/agent-performance.d.ts.map +1 -0
- package/dist/services/approval-manager.d.ts +30 -0
- package/dist/services/approval-manager.d.ts.map +1 -0
- package/dist/services/index.d.ts +7 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/model-router.d.ts +35 -0
- package/dist/services/model-router.d.ts.map +1 -0
- package/dist/services/policy-compiler.d.ts +27 -0
- package/dist/services/policy-compiler.d.ts.map +1 -0
- package/dist/services/run-trace.d.ts +34 -0
- package/dist/services/run-trace.d.ts.map +1 -0
- package/dist/services/services.test.d.ts +2 -0
- package/dist/services/services.test.d.ts.map +1 -0
- package/dist/services/telemetry.d.ts +34 -0
- package/dist/services/telemetry.d.ts.map +1 -0
- package/dist/tools/agent-dispatch.test.d.ts +2 -0
- package/dist/tools/agent-dispatch.test.d.ts.map +1 -0
- package/dist/tools/codebase-state.d.ts +4 -0
- package/dist/tools/codebase-state.d.ts.map +1 -0
- package/dist/tools/context-generator.d.ts +3 -0
- package/dist/tools/context-generator.d.ts.map +1 -0
- package/dist/tools/council.d.ts +4 -0
- package/dist/tools/council.d.ts.map +1 -0
- package/dist/tools/decision-trace.d.ts +16 -0
- package/dist/tools/decision-trace.d.ts.map +1 -0
- package/dist/tools/delegate.d.ts +4 -0
- package/dist/tools/delegate.d.ts.map +1 -0
- package/dist/tools/failure-replay.d.ts +19 -0
- package/dist/tools/failure-replay.d.ts.map +1 -0
- package/dist/tools/failure-replay.test.d.ts +2 -0
- package/dist/tools/failure-replay.test.d.ts.map +1 -0
- package/dist/tools/hash-edit.d.ts +3 -0
- package/dist/tools/hash-edit.d.ts.map +1 -0
- package/dist/tools/planning-state-lib.d.ts +65 -0
- package/dist/tools/planning-state-lib.d.ts.map +1 -0
- package/dist/tools/planning-state.d.ts +3 -0
- package/dist/tools/planning-state.d.ts.map +1 -0
- package/dist/tools/policy-engine.d.ts +19 -0
- package/dist/tools/policy-engine.d.ts.map +1 -0
- package/dist/tools/repo-memory.d.ts +20 -0
- package/dist/tools/repo-memory.d.ts.map +1 -0
- package/dist/tools/repo-memory.test.d.ts +2 -0
- package/dist/tools/repo-memory.test.d.ts.map +1 -0
- package/dist/tools/run-parallel.d.ts +4 -0
- package/dist/tools/run-parallel.d.ts.map +1 -0
- package/dist/tools/run-pipeline.d.ts +4 -0
- package/dist/tools/run-pipeline.d.ts.map +1 -0
- package/dist/tools/volatility-map.d.ts +18 -0
- package/dist/tools/volatility-map.d.ts.map +1 -0
- package/dist/tools/volatility-map.test.d.ts +2 -0
- package/dist/tools/volatility-map.test.d.ts.map +1 -0
- package/dist/tools/workspace-state.d.ts +3 -0
- package/dist/tools/workspace-state.d.ts.map +1 -0
- package/docs/USER_GUIDE.md +20 -0
- package/docs/agents.md +562 -0
- package/docs/best-practices.md +47 -0
- package/docs/command-migration.md +175 -0
- package/docs/commands/fd-analyze-change.md +107 -0
- package/docs/commands/fd-ask.md +51 -0
- package/docs/commands/fd-checkpoint.md +10 -0
- package/docs/commands/fd-dashboard.md +11 -0
- package/docs/commands/fd-deploy-check.md +11 -0
- package/docs/commands/fd-discuss.md +28 -0
- package/docs/commands/fd-evaluate-risk.md +134 -0
- package/docs/commands/fd-fix-bug.md +24 -0
- package/docs/commands/fd-guarded-edit.md +105 -0
- package/docs/commands/fd-map-codebase.md +27 -0
- package/docs/commands/fd-multi-repo.md +63 -0
- package/docs/commands/fd-new-feature.md +25 -0
- package/docs/commands/fd-new-project.md +24 -0
- package/docs/commands/fd-plan.md +33 -0
- package/docs/commands/fd-progress.md +11 -0
- package/docs/commands/fd-resume.md +10 -0
- package/docs/commands/fd-review-code.md +29 -0
- package/docs/commands/fd-roadmap.md +10 -0
- package/docs/commands/fd-settings.md +10 -0
- package/docs/commands/fd-write-docs.md +10 -0
- package/docs/commands.md +476 -0
- package/docs/configuration.md +211 -0
- package/docs/feature-integration-architecture.md +255 -0
- package/docs/index.md +75 -0
- package/docs/installation.md +134 -0
- package/docs/intelligence.md +294 -0
- package/docs/multi-repo.md +201 -0
- package/docs/notifications.md +170 -0
- package/docs/parallel-execution.md +227 -0
- package/docs/quick-start.md +174 -0
- package/docs/rules.md +459 -0
- package/docs/skills.md +408 -0
- package/docs/workflows.md +376 -0
- package/package.json +58 -0
- package/postinstall.mjs +102 -0
- package/src/rules/README.md +37 -0
- package/src/rules/common/agent-orchestration.md +86 -0
- package/src/rules/common/coding-style.md +120 -0
- package/src/rules/common/git-workflow.md +77 -0
- package/src/rules/common/security.md +94 -0
- package/src/rules/common/testing.md +105 -0
- package/src/rules/golang/patterns.md +187 -0
- package/src/rules/java/patterns.md +204 -0
- package/src/rules/python/patterns.md +141 -0
- package/src/rules/rust/patterns.md +210 -0
- package/src/rules/typescript/patterns.md +168 -0
- package/src/skills/api-design/SKILL.md +143 -0
- package/src/skills/arch-constraint-guard/SKILL.md +61 -0
- package/src/skills/blast-radius-preview/SKILL.md +65 -0
- package/src/skills/change-impact-radar/SKILL.md +63 -0
- package/src/skills/code-review/SKILL.md +108 -0
- package/src/skills/code-tour/SKILL.md +101 -0
- package/src/skills/codebase-mapping/SKILL.md +87 -0
- package/src/skills/codebase-onboarding/SKILL.md +133 -0
- package/src/skills/confidence-aware-planning/SKILL.md +67 -0
- package/src/skills/context-load/SKILL.md +63 -0
- package/src/skills/debug-flow/SKILL.md +75 -0
- package/src/skills/decision-trace/SKILL.md +72 -0
- package/src/skills/dependency-audit/SKILL.md +126 -0
- package/src/skills/deploy-check/SKILL.md +87 -0
- package/src/skills/documentation-writer/SKILL.md +154 -0
- package/src/skills/failure-replay-engine/SKILL.md +59 -0
- package/src/skills/git-release/SKILL.md +94 -0
- package/src/skills/git-workflow/SKILL.md +177 -0
- package/src/skills/golang-patterns/SKILL.md +511 -0
- package/src/skills/human-review-routing/SKILL.md +65 -0
- package/src/skills/intent-translator/SKILL.md +57 -0
- package/src/skills/java-patterns/SKILL.md +479 -0
- package/src/skills/multi-repo/SKILL.md +187 -0
- package/src/skills/parallel-execute/SKILL.md +92 -0
- package/src/skills/patch-trust-score/SKILL.md +44 -0
- package/src/skills/performance-profiling/SKILL.md +153 -0
- package/src/skills/plan-task/SKILL.md +101 -0
- package/src/skills/python-patterns/SKILL.md +529 -0
- package/src/skills/refactor-guide/SKILL.md +117 -0
- package/src/skills/regression-prediction/SKILL.md +57 -0
- package/src/skills/repo-memory-graph/SKILL.md +49 -0
- package/src/skills/rust-patterns/SKILL.md +492 -0
- package/src/skills/security-scan/SKILL.md +91 -0
- package/src/skills/self-healing-policies/SKILL.md +76 -0
- package/src/skills/tdd-workflow/SKILL.md +126 -0
- package/src/skills/test-coverage/SKILL.md +94 -0
- package/src/skills/test-gap-detector/SKILL.md +58 -0
- package/src/skills/volatility-map/SKILL.md +52 -0
- package/src/workflows/debug-flow.md +119 -0
- package/src/workflows/deploy-check-flow.md +98 -0
- package/src/workflows/discuss-flow.md +97 -0
- package/src/workflows/execute-flow.md +233 -0
- package/src/workflows/execute-phase.md +142 -0
- package/src/workflows/fix-bug-flow.md +210 -0
- package/src/workflows/map-codebase-flow.md +92 -0
- package/src/workflows/multi-repo-flow.md +226 -0
- package/src/workflows/parallel-execution-flow.md +236 -0
- package/src/workflows/plan-flow.md +126 -0
- package/src/workflows/plan-phase.md +101 -0
- package/src/workflows/refactor-flow.md +122 -0
- package/src/workflows/review-code-flow.md +105 -0
- package/src/workflows/spec-driven-flow.md +43 -0
- package/src/workflows/write-docs-flow.md +95 -0
|
@@ -0,0 +1,511 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: golang-patterns
|
|
3
|
+
description: Idiomatic Go patterns covering error handling, interfaces, goroutines, channels, testing, and common pitfalls. Activate when writing or reviewing Go code.
|
|
4
|
+
origin: FlowDeck
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Go Patterns Skill
|
|
8
|
+
|
|
9
|
+
Idiomatic Go for production systems. Focuses on simplicity, explicitness, and composition.
|
|
10
|
+
|
|
11
|
+
## When to Activate
|
|
12
|
+
|
|
13
|
+
Activate when:
|
|
14
|
+
- Writing new Go packages or services
|
|
15
|
+
- Reviewing Go code for idiom and correctness
|
|
16
|
+
- Designing concurrent processing pipelines
|
|
17
|
+
- Debugging goroutine leaks or race conditions
|
|
18
|
+
- Setting up module structure or build configuration
|
|
19
|
+
|
|
20
|
+
## Error Handling
|
|
21
|
+
|
|
22
|
+
Go errors are values. Handle them at the point where you have enough context to act.
|
|
23
|
+
|
|
24
|
+
### Wrapping and Unwrapping
|
|
25
|
+
|
|
26
|
+
```go
|
|
27
|
+
import "errors"
|
|
28
|
+
import "fmt"
|
|
29
|
+
|
|
30
|
+
// Wrap with %w to preserve the chain
|
|
31
|
+
func loadConfig(path string) (*Config, error) {
|
|
32
|
+
data, err := os.ReadFile(path)
|
|
33
|
+
if err != nil {
|
|
34
|
+
return nil, fmt.Errorf("loadConfig %q: %w", path, err)
|
|
35
|
+
}
|
|
36
|
+
// ...
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Inspect with errors.Is (sentinel) and errors.As (type)
|
|
40
|
+
var ErrNotFound = errors.New("not found")
|
|
41
|
+
|
|
42
|
+
if err := loadConfig("app.yaml"); err != nil {
|
|
43
|
+
if errors.Is(err, os.ErrNotExist) {
|
|
44
|
+
// file missing
|
|
45
|
+
}
|
|
46
|
+
var pathErr *os.PathError
|
|
47
|
+
if errors.As(err, &pathErr) {
|
|
48
|
+
log.Printf("path problem: %s", pathErr.Path)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Sentinel Errors
|
|
54
|
+
|
|
55
|
+
```go
|
|
56
|
+
// Define at package level, exported when callers need to check
|
|
57
|
+
var (
|
|
58
|
+
ErrNotFound = errors.New("not found")
|
|
59
|
+
ErrPermission = errors.New("permission denied")
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
// Prefer typed errors when you need to attach data
|
|
63
|
+
type ValidationError struct {
|
|
64
|
+
Field string
|
|
65
|
+
Message string
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
func (e *ValidationError) Error() string {
|
|
69
|
+
return fmt.Sprintf("validation: %s %s", e.Field, e.Message)
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Error String Conventions
|
|
74
|
+
|
|
75
|
+
```go
|
|
76
|
+
// ✅ lowercase, no trailing punctuation
|
|
77
|
+
errors.New("connection refused")
|
|
78
|
+
fmt.Errorf("user %d not found", id)
|
|
79
|
+
|
|
80
|
+
// ❌ uppercase or punctuation
|
|
81
|
+
errors.New("Connection refused.")
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Interface Design
|
|
85
|
+
|
|
86
|
+
Keep interfaces small. A one-method interface is a feature, not a limitation.
|
|
87
|
+
|
|
88
|
+
### The io.Reader / io.Writer Pattern
|
|
89
|
+
|
|
90
|
+
```go
|
|
91
|
+
// Standard library interfaces — use them where they fit
|
|
92
|
+
type Reader interface {
|
|
93
|
+
Read(p []byte) (n int, err error)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
type Writer interface {
|
|
97
|
+
Write(p []byte) (n int, err error)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Compose for more complex contracts
|
|
101
|
+
type ReadWriter interface {
|
|
102
|
+
Reader
|
|
103
|
+
Writer
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Accept interfaces, return concrete types
|
|
107
|
+
func Process(r io.Reader) ([]byte, error) {
|
|
108
|
+
return io.ReadAll(r)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// os.File, bytes.Buffer, http.Response.Body all satisfy io.Reader
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Define Interfaces at the Consumer
|
|
115
|
+
|
|
116
|
+
```go
|
|
117
|
+
// ❌ Defining in the producer package forces coupling
|
|
118
|
+
package store
|
|
119
|
+
type Repository interface { ... } // in the store package
|
|
120
|
+
|
|
121
|
+
// ✅ Define in the consumer package
|
|
122
|
+
package service
|
|
123
|
+
type userStore interface {
|
|
124
|
+
FindByID(ctx context.Context, id int64) (*User, error)
|
|
125
|
+
Save(ctx context.Context, u *User) error
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
type UserService struct {
|
|
129
|
+
store userStore
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Single-Method Naming
|
|
134
|
+
|
|
135
|
+
```go
|
|
136
|
+
// Verb + "er" for single-method interfaces
|
|
137
|
+
type Reader interface { Read(...) }
|
|
138
|
+
type Writer interface { Write(...) }
|
|
139
|
+
type Stringer interface { String() string }
|
|
140
|
+
type Closer interface { Close() error }
|
|
141
|
+
type Handler interface { ServeHTTP(...) }
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Goroutines and Channels
|
|
145
|
+
|
|
146
|
+
### Worker Pool Pattern
|
|
147
|
+
|
|
148
|
+
```go
|
|
149
|
+
func workerPool(ctx context.Context, jobs <-chan Job, workers int) <-chan Result {
|
|
150
|
+
results := make(chan Result)
|
|
151
|
+
|
|
152
|
+
var wg sync.WaitGroup
|
|
153
|
+
wg.Add(workers)
|
|
154
|
+
for range workers {
|
|
155
|
+
go func() {
|
|
156
|
+
defer wg.Done()
|
|
157
|
+
for job := range jobs {
|
|
158
|
+
select {
|
|
159
|
+
case results <- process(job):
|
|
160
|
+
case <-ctx.Done():
|
|
161
|
+
return
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}()
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
go func() {
|
|
168
|
+
wg.Wait()
|
|
169
|
+
close(results)
|
|
170
|
+
}()
|
|
171
|
+
|
|
172
|
+
return results
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Fan-Out / Fan-In
|
|
177
|
+
|
|
178
|
+
```go
|
|
179
|
+
// Fan-out: send work to N goroutines
|
|
180
|
+
func fanOut(in <-chan int, n int) []<-chan int {
|
|
181
|
+
outs := make([]<-chan int, n)
|
|
182
|
+
for i := range n {
|
|
183
|
+
ch := make(chan int)
|
|
184
|
+
outs[i] = ch
|
|
185
|
+
go func() {
|
|
186
|
+
defer close(ch)
|
|
187
|
+
for v := range in {
|
|
188
|
+
ch <- v * 2
|
|
189
|
+
}
|
|
190
|
+
}()
|
|
191
|
+
}
|
|
192
|
+
return outs
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Fan-in: merge N channels into one
|
|
196
|
+
func merge(channels ...<-chan int) <-chan int {
|
|
197
|
+
out := make(chan int)
|
|
198
|
+
var wg sync.WaitGroup
|
|
199
|
+
wg.Add(len(channels))
|
|
200
|
+
for _, ch := range channels {
|
|
201
|
+
go func(c <-chan int) {
|
|
202
|
+
defer wg.Done()
|
|
203
|
+
for v := range c {
|
|
204
|
+
out <- v
|
|
205
|
+
}
|
|
206
|
+
}(ch)
|
|
207
|
+
}
|
|
208
|
+
go func() {
|
|
209
|
+
wg.Wait()
|
|
210
|
+
close(out)
|
|
211
|
+
}()
|
|
212
|
+
return out
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Select and Context Cancellation
|
|
217
|
+
|
|
218
|
+
```go
|
|
219
|
+
func doWork(ctx context.Context) error {
|
|
220
|
+
ticker := time.NewTicker(500 * time.Millisecond)
|
|
221
|
+
defer ticker.Stop()
|
|
222
|
+
|
|
223
|
+
for {
|
|
224
|
+
select {
|
|
225
|
+
case <-ctx.Done():
|
|
226
|
+
return ctx.Err()
|
|
227
|
+
case t := <-ticker.C:
|
|
228
|
+
if err := tick(t); err != nil {
|
|
229
|
+
return fmt.Errorf("tick: %w", err)
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Channel Ownership Rule
|
|
237
|
+
|
|
238
|
+
The goroutine that creates a channel is responsible for closing it. Closing a channel from a reader or having multiple goroutines close the same channel causes panics.
|
|
239
|
+
|
|
240
|
+
## Struct Embedding vs Composition
|
|
241
|
+
|
|
242
|
+
### Embedding for Behaviour Promotion
|
|
243
|
+
|
|
244
|
+
```go
|
|
245
|
+
type Logger struct {
|
|
246
|
+
level string
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
func (l *Logger) Log(msg string) {
|
|
250
|
+
fmt.Printf("[%s] %s\n", l.level, msg)
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
type Server struct {
|
|
254
|
+
Logger // promotes Log method
|
|
255
|
+
addr string
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
s := Server{Logger: Logger{level: "INFO"}, addr: ":8080"}
|
|
259
|
+
s.Log("starting") // calls s.Logger.Log
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Prefer Explicit Fields for Data
|
|
263
|
+
|
|
264
|
+
```go
|
|
265
|
+
// ❌ Embedding for data models creates implicit API surface
|
|
266
|
+
type FullUser struct {
|
|
267
|
+
User // every User field/method becomes part of FullUser's API
|
|
268
|
+
Profile
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// ✅ Explicit fields make dependencies obvious
|
|
272
|
+
type FullUser struct {
|
|
273
|
+
User User
|
|
274
|
+
Profile Profile
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## defer, panic, recover
|
|
279
|
+
|
|
280
|
+
### defer — Always for Cleanup
|
|
281
|
+
|
|
282
|
+
```go
|
|
283
|
+
func writeFile(path string, data []byte) error {
|
|
284
|
+
f, err := os.Create(path)
|
|
285
|
+
if err != nil {
|
|
286
|
+
return err
|
|
287
|
+
}
|
|
288
|
+
defer f.Close() // runs even if Write returns error
|
|
289
|
+
|
|
290
|
+
_, err = f.Write(data)
|
|
291
|
+
return err
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// defer evaluates arguments immediately — useful for timing
|
|
295
|
+
func trace(name string) func() {
|
|
296
|
+
start := time.Now()
|
|
297
|
+
return func() { log.Printf("%s: %v", name, time.Since(start)) }
|
|
298
|
+
}
|
|
299
|
+
defer trace("expensiveOp")()
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### panic / recover — Only at Boundaries
|
|
303
|
+
|
|
304
|
+
```go
|
|
305
|
+
// Use panic only for programmer errors (invariant violations)
|
|
306
|
+
func mustPositive(n int) int {
|
|
307
|
+
if n <= 0 {
|
|
308
|
+
panic(fmt.Sprintf("expected positive, got %d", n))
|
|
309
|
+
}
|
|
310
|
+
return n
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Recover at the top of a goroutine or HTTP handler to convert to error
|
|
314
|
+
func safeExec(fn func()) (err error) {
|
|
315
|
+
defer func() {
|
|
316
|
+
if r := recover(); r != nil {
|
|
317
|
+
err = fmt.Errorf("panic: %v", r)
|
|
318
|
+
}
|
|
319
|
+
}()
|
|
320
|
+
fn()
|
|
321
|
+
return nil
|
|
322
|
+
}
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
Never use panic/recover as a substitute for regular error handling.
|
|
326
|
+
|
|
327
|
+
## Table-Driven Tests
|
|
328
|
+
|
|
329
|
+
```go
|
|
330
|
+
func TestParseDate(t *testing.T) {
|
|
331
|
+
cases := []struct {
|
|
332
|
+
name string
|
|
333
|
+
input string
|
|
334
|
+
want time.Time
|
|
335
|
+
wantErr bool
|
|
336
|
+
}{
|
|
337
|
+
{
|
|
338
|
+
name: "ISO format",
|
|
339
|
+
input: "2024-01-15",
|
|
340
|
+
want: time.Date(2024, 1, 15, 0, 0, 0, 0, time.UTC),
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
name: "empty string",
|
|
344
|
+
input: "",
|
|
345
|
+
wantErr: true,
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
name: "invalid format",
|
|
349
|
+
input: "15/01/2024",
|
|
350
|
+
wantErr: true,
|
|
351
|
+
},
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
for _, tc := range cases {
|
|
355
|
+
t.Run(tc.name, func(t *testing.T) {
|
|
356
|
+
got, err := ParseDate(tc.input)
|
|
357
|
+
if (err != nil) != tc.wantErr {
|
|
358
|
+
t.Fatalf("ParseDate(%q) error = %v, wantErr %v", tc.input, err, tc.wantErr)
|
|
359
|
+
}
|
|
360
|
+
if !tc.wantErr && !got.Equal(tc.want) {
|
|
361
|
+
t.Errorf("ParseDate(%q) = %v, want %v", tc.input, got, tc.want)
|
|
362
|
+
}
|
|
363
|
+
})
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
## Go Modules
|
|
369
|
+
|
|
370
|
+
### go.mod Structure
|
|
371
|
+
|
|
372
|
+
```
|
|
373
|
+
module github.com/org/myservice
|
|
374
|
+
|
|
375
|
+
go 1.23
|
|
376
|
+
|
|
377
|
+
require (
|
|
378
|
+
github.com/some/dep v1.2.3
|
|
379
|
+
)
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### Workspace Mode (go.work) for Multi-Module Repos
|
|
383
|
+
|
|
384
|
+
```
|
|
385
|
+
go 1.23
|
|
386
|
+
|
|
387
|
+
use (
|
|
388
|
+
./cmd/api
|
|
389
|
+
./internal/core
|
|
390
|
+
./pkg/client
|
|
391
|
+
)
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
```bash
|
|
395
|
+
go work init ./cmd/api ./internal/core
|
|
396
|
+
go work use ./pkg/client
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
### Module Commands
|
|
400
|
+
|
|
401
|
+
```bash
|
|
402
|
+
go mod tidy # add missing, remove unused
|
|
403
|
+
go mod vendor # copy deps to vendor/
|
|
404
|
+
go get github.com/x@v1.2.3 # add or upgrade
|
|
405
|
+
go mod why github.com/x # explain why dep is needed
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
## sync Package
|
|
409
|
+
|
|
410
|
+
```go
|
|
411
|
+
var mu sync.Mutex
|
|
412
|
+
mu.Lock()
|
|
413
|
+
defer mu.Unlock()
|
|
414
|
+
|
|
415
|
+
// RWMutex — many readers, one writer
|
|
416
|
+
var rw sync.RWMutex
|
|
417
|
+
rw.RLock()
|
|
418
|
+
defer rw.RUnlock()
|
|
419
|
+
|
|
420
|
+
// WaitGroup — wait for goroutines to finish
|
|
421
|
+
var wg sync.WaitGroup
|
|
422
|
+
wg.Add(1)
|
|
423
|
+
go func() {
|
|
424
|
+
defer wg.Done()
|
|
425
|
+
// ...
|
|
426
|
+
}()
|
|
427
|
+
wg.Wait()
|
|
428
|
+
|
|
429
|
+
// Once — run exactly once (e.g., lazy init)
|
|
430
|
+
var once sync.Once
|
|
431
|
+
var instance *DB
|
|
432
|
+
func getDB() *DB {
|
|
433
|
+
once.Do(func() { instance = newDB() })
|
|
434
|
+
return instance
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// Atomic operations — simple counters without a mutex
|
|
438
|
+
var counter atomic.Int64
|
|
439
|
+
counter.Add(1)
|
|
440
|
+
n := counter.Load()
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
## Build Tags
|
|
444
|
+
|
|
445
|
+
```go
|
|
446
|
+
//go:build linux && amd64
|
|
447
|
+
|
|
448
|
+
package platform
|
|
449
|
+
|
|
450
|
+
// This file only compiles on 64-bit Linux.
|
|
451
|
+
func pageSize() int { return 4096 }
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
```bash
|
|
455
|
+
go build -tags integration ./...
|
|
456
|
+
go test -tags integration ./...
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
## Common Pitfalls
|
|
460
|
+
|
|
461
|
+
### Goroutine Leaks
|
|
462
|
+
|
|
463
|
+
```go
|
|
464
|
+
// ❌ Nothing reads from results — goroutines block forever
|
|
465
|
+
func leak() {
|
|
466
|
+
results := make(chan int)
|
|
467
|
+
go func() { results <- compute() }()
|
|
468
|
+
// forgot to read results
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// ✅ Always ensure goroutines can exit — use buffered channels or context
|
|
472
|
+
func noLeak(ctx context.Context) {
|
|
473
|
+
results := make(chan int, 1)
|
|
474
|
+
go func() {
|
|
475
|
+
select {
|
|
476
|
+
case results <- compute():
|
|
477
|
+
case <-ctx.Done():
|
|
478
|
+
}
|
|
479
|
+
}()
|
|
480
|
+
}
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
### nil Interface vs nil Pointer
|
|
484
|
+
|
|
485
|
+
```go
|
|
486
|
+
// ❌ Returning a typed nil as an interface is NOT nil
|
|
487
|
+
func getErr() error {
|
|
488
|
+
var p *os.PathError = nil
|
|
489
|
+
return p // error interface is not nil!
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// ✅ Return untyped nil
|
|
493
|
+
func getErr() error {
|
|
494
|
+
return nil
|
|
495
|
+
}
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
### Map Race Conditions
|
|
499
|
+
|
|
500
|
+
```go
|
|
501
|
+
// ❌ Concurrent read/write on map causes data race
|
|
502
|
+
m := map[string]int{}
|
|
503
|
+
go func() { m["a"] = 1 }()
|
|
504
|
+
go func() { _ = m["a"] }()
|
|
505
|
+
|
|
506
|
+
// ✅ Use sync.Map or protect with a mutex
|
|
507
|
+
var mu sync.RWMutex
|
|
508
|
+
mu.Lock()
|
|
509
|
+
m["a"] = 1
|
|
510
|
+
mu.Unlock()
|
|
511
|
+
```
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: human-review-routing
|
|
3
|
+
description: Route risky patches to the right reviewer type — security, backend, infra, or domain owner — based on the nature of the change and its patch trust score.
|
|
4
|
+
origin: FlowDeck
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Human Review Routing
|
|
8
|
+
|
|
9
|
+
When a patch is flagged as `review-required` or `high-risk` by the Patch Trust Score, it must be routed to the right human reviewer. This skill defines the routing logic.
|
|
10
|
+
|
|
11
|
+
## Reviewer Types and Triggers
|
|
12
|
+
|
|
13
|
+
| Reviewer | Triggered by |
|
|
14
|
+
|----------|-------------|
|
|
15
|
+
| security | auth, token, password, crypto, secret, jwt, permission, rbac, xss, sql |
|
|
16
|
+
| backend | api, route, controller, service, database, query, migration |
|
|
17
|
+
| infra | docker, kubernetes, terraform, ci, cd, deploy, helm, nginx, aws, gcp |
|
|
18
|
+
| domain-owner | business, billing, payment, checkout, order, subscription, pricing |
|
|
19
|
+
| frontend | component, css, html, react, vue, ui, ux, style |
|
|
20
|
+
| data | schema, migration, model, index, constraint, foreign key |
|
|
21
|
+
| devops | pipeline, workflow, .yml, .yaml, action, cron, schedule |
|
|
22
|
+
|
|
23
|
+
## Routing Logic
|
|
24
|
+
|
|
25
|
+
1. Scan the changed file paths and change description for keywords from the table above
|
|
26
|
+
2. Check the Patch Trust Score verdict
|
|
27
|
+
3. **High-risk** always adds `security` to the reviewer list
|
|
28
|
+
4. Multiple reviewer types can be assigned to one patch
|
|
29
|
+
5. If no keywords match and verdict is `safe`, route to `general-reviewer`
|
|
30
|
+
|
|
31
|
+
## Workflow
|
|
32
|
+
|
|
33
|
+
Run `/review-route` with `--files` and `--change` to get the routing decision.
|
|
34
|
+
|
|
35
|
+
Example:
|
|
36
|
+
```
|
|
37
|
+
/review-route {"files": "src/services/auth.ts,src/api/payment.ts", "change": "refactor JWT validation"}
|
|
38
|
+
```
|
|
39
|
+
Output:
|
|
40
|
+
```
|
|
41
|
+
Route to: security, backend, domain-owner
|
|
42
|
+
Trust verdict: review-required
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Review Request Format
|
|
46
|
+
|
|
47
|
+
When routing a patch, include:
|
|
48
|
+
```markdown
|
|
49
|
+
## Review Request
|
|
50
|
+
|
|
51
|
+
**Patch**: [brief description]
|
|
52
|
+
**Files**: [list]
|
|
53
|
+
**Trust Score**: [score] ([verdict])
|
|
54
|
+
**Route to**: [reviewer types]
|
|
55
|
+
**Reason**: [why this routing]
|
|
56
|
+
**Deadline**: [if blocking release]
|
|
57
|
+
|
|
58
|
+
### Key areas to check
|
|
59
|
+
- [specific concern 1]
|
|
60
|
+
- [specific concern 2]
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Escalation
|
|
64
|
+
|
|
65
|
+
If no appropriate reviewer is available within 24h, escalate to the tech lead. Never merge a `high-risk` patch without at least one human approval.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: intent-translator
|
|
3
|
+
description: Convert vague requests like "make checkout faster" into concrete, ranked implementation options with tradeoffs before coding starts.
|
|
4
|
+
origin: FlowDeck
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Intent-to-Change Translator
|
|
8
|
+
|
|
9
|
+
Run `/translate-intent` with a plain-language description of what you want. Get back a ranked menu of concrete implementation options with tradeoffs — before writing a single line of code.
|
|
10
|
+
|
|
11
|
+
## When to Activate
|
|
12
|
+
|
|
13
|
+
- The request is vague ("make it faster", "improve reliability", "clean this up")
|
|
14
|
+
- Multiple valid approaches exist and the choice has significant consequences
|
|
15
|
+
- The user hasn't specified which files or systems to touch
|
|
16
|
+
|
|
17
|
+
## Workflow
|
|
18
|
+
|
|
19
|
+
1. Parse the intent: what outcome is the user seeking?
|
|
20
|
+
2. Search the codebase for relevant context:
|
|
21
|
+
- What does the system currently do in this area?
|
|
22
|
+
- What are the bottlenecks or pain points?
|
|
23
|
+
3. Generate ≤5 concrete implementation options, each with:
|
|
24
|
+
- **Name**: short label
|
|
25
|
+
- **Description**: 1–2 sentences of what it does
|
|
26
|
+
- **Files affected**: list of files to touch
|
|
27
|
+
- **Effort**: S (hours) / M (1–2 days) / L (week+)
|
|
28
|
+
- **Risk**: low / medium / high
|
|
29
|
+
- **Tradeoffs**: what you gain and what you give up
|
|
30
|
+
4. Rank options by impact-to-effort ratio (best first)
|
|
31
|
+
5. Ask clarifying questions if the intent is still ambiguous after step 2
|
|
32
|
+
|
|
33
|
+
## Output Format
|
|
34
|
+
|
|
35
|
+
```markdown
|
|
36
|
+
## Intent Translation: "[original intent]"
|
|
37
|
+
|
|
38
|
+
### Option 1 (Recommended): [Name]
|
|
39
|
+
**Description**: [what it does]
|
|
40
|
+
**Files**: [list]
|
|
41
|
+
**Effort**: S | M | L **Risk**: low | medium | high
|
|
42
|
+
**Tradeoffs**: ✅ [gain] | ⚠️ [cost]
|
|
43
|
+
|
|
44
|
+
### Option 2: [Name]
|
|
45
|
+
...
|
|
46
|
+
|
|
47
|
+
### Clarifying Questions (if needed)
|
|
48
|
+
1. [question]
|
|
49
|
+
|
|
50
|
+
### Recommendation
|
|
51
|
+
Proceed with **Option 1** because [reason].
|
|
52
|
+
To start: run `/plan` after confirming your choice.
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Confidence Rule
|
|
56
|
+
|
|
57
|
+
If the intent could mean two fundamentally different things, list both interpretations explicitly and ask the user to choose BEFORE generating options. Do not guess silently.
|