triples-agentic 2.4.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.
Files changed (77) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +326 -0
  3. package/docs/workflow.md +163 -0
  4. package/install.sh +98 -0
  5. package/package.json +54 -0
  6. package/src/agents/README.md +85 -0
  7. package/src/agents/jiwoo-prd.md +84 -0
  8. package/src/agents/kaede-backend.md +95 -0
  9. package/src/agents/kotone-flutter.md +100 -0
  10. package/src/agents/lynn-testcase.md +92 -0
  11. package/src/agents/nakyoung-tasks.md +89 -0
  12. package/src/agents/seoyeon.md +76 -0
  13. package/src/agents/shion-qa.md +89 -0
  14. package/src/agents/sohyun-ios.md +97 -0
  15. package/src/agents/yeonji-android.md +98 -0
  16. package/src/agents/yooyeon-rfc.md +82 -0
  17. package/src/agents/yubin-frontend.md +88 -0
  18. package/src/bin/setup.js +640 -0
  19. package/src/hooks/README.md +102 -0
  20. package/src/hooks/dangerous-commands.json +33 -0
  21. package/src/hooks/dangerous-commands.md +18 -0
  22. package/src/knowledge/README.md +129 -0
  23. package/src/knowledge/general/boy-scout-rule.md +13 -0
  24. package/src/knowledge/general/composition-over-inheritance.md +14 -0
  25. package/src/knowledge/general/dry.md +14 -0
  26. package/src/knowledge/general/fail-fast.md +13 -0
  27. package/src/knowledge/general/kiss.md +15 -0
  28. package/src/knowledge/general/least-surprise.md +13 -0
  29. package/src/knowledge/general/slap.md +29 -0
  30. package/src/knowledge/general/solid.md +44 -0
  31. package/src/knowledge/general/tdd.md +76 -0
  32. package/src/knowledge/general/yagni.md +12 -0
  33. package/src/knowledge/mobile/android/android-architecture.md +83 -0
  34. package/src/knowledge/mobile/android/android-platform.md +60 -0
  35. package/src/knowledge/mobile/android/kotlin-concurrency.md +75 -0
  36. package/src/knowledge/mobile/android/kotlin-core.md +88 -0
  37. package/src/knowledge/mobile/flutter/dart-async.md +93 -0
  38. package/src/knowledge/mobile/flutter/dart-core.md +97 -0
  39. package/src/knowledge/mobile/flutter/flutter-architecture.md +88 -0
  40. package/src/knowledge/mobile/flutter/flutter-platform.md +79 -0
  41. package/src/knowledge/mobile/ios/ios-architecture.md +88 -0
  42. package/src/knowledge/mobile/ios/ios-platform.md +66 -0
  43. package/src/knowledge/mobile/ios/swift-concurrency.md +99 -0
  44. package/src/knowledge/mobile/ios/swift-core.md +79 -0
  45. package/src/knowledge/planning/architecture-database.md +47 -0
  46. package/src/knowledge/planning/architecture-patterns.md +64 -0
  47. package/src/knowledge/planning/architecture-security.md +61 -0
  48. package/src/knowledge/planning/estimation.md +82 -0
  49. package/src/knowledge/planning/orchestration.md +70 -0
  50. package/src/knowledge/planning/prd-quality-gates.md +38 -0
  51. package/src/knowledge/planning/prd-writing.md +59 -0
  52. package/src/knowledge/planning/product-principles.md +48 -0
  53. package/src/knowledge/planning/product-prioritization.md +45 -0
  54. package/src/knowledge/planning/rfc-quality-gates.md +38 -0
  55. package/src/knowledge/planning/rfc-writing.md +81 -0
  56. package/src/knowledge/planning/task-decomposition.md +61 -0
  57. package/src/knowledge/planning/task-readiness.md +64 -0
  58. package/src/knowledge/quality/qa-execution.md +55 -0
  59. package/src/knowledge/quality/qa-reporting.md +71 -0
  60. package/src/knowledge/quality/test-case-quality.md +61 -0
  61. package/src/knowledge/quality/test-case-writing.md +76 -0
  62. package/src/knowledge/quality/testing-strategy.md +70 -0
  63. package/src/knowledge/quality/testing-types.md +84 -0
  64. package/src/knowledge/web/backend/api-design.md +74 -0
  65. package/src/knowledge/web/backend/api-security.md +54 -0
  66. package/src/knowledge/web/backend/backend-security.md +84 -0
  67. package/src/knowledge/web/backend/backend-structure.md +78 -0
  68. package/src/knowledge/web/frontend/frontend-components.md +49 -0
  69. package/src/knowledge/web/frontend/frontend-performance.md +41 -0
  70. package/src/knowledge/web/frontend/frontend-state.md +59 -0
  71. package/src/knowledge/web/frontend/web-accessibility.md +51 -0
  72. package/src/knowledge/web/frontend/web-performance.md +51 -0
  73. package/src/knowledge/web/frontend/web-security.md +59 -0
  74. package/src/templates/prd.md +109 -0
  75. package/src/templates/rfc.md +156 -0
  76. package/src/templates/task-breakdown.md +172 -0
  77. package/src/templates/test-case.md +157 -0
@@ -0,0 +1,102 @@
1
+ # hooks/
2
+
3
+ Safety guardrail definitions — the source of truth for dangerous-command blocking across all platforms.
4
+
5
+ The installer reads these files and generates platform-specific hook configs. Edit here, reinstall, and every platform gets the update.
6
+
7
+ ---
8
+
9
+ ## Files
10
+
11
+ | File | Purpose |
12
+ |---|---|
13
+ | `dangerous-commands.json` | Per-platform executable hook configs (Claude Code, Codex, Windsurf) |
14
+ | `dangerous-commands.md` | Text-based safety rules for platforms without executable hooks (Cursor, Copilot) |
15
+
16
+ ---
17
+
18
+ ## `*.json` — Executable hook configs
19
+
20
+ Each JSON file describes one safety rule and carries per-platform configurations under a `platforms` key.
21
+
22
+ ```json
23
+ {
24
+ "name": "dangerous-commands",
25
+ "description": "Block dangerous shell commands before execution",
26
+ "platforms": {
27
+ "claude": {
28
+ "event": "PreToolUse",
29
+ "matcher": "Bash",
30
+ "hooks": [{ "type": "command", "command": "...", "statusMessage": "..." }]
31
+ },
32
+ "codex": {
33
+ "event": "PreToolUse",
34
+ "matcher": "Bash",
35
+ "hooks": [{ "type": "command", "command": "...", "statusMessage": "..." }]
36
+ },
37
+ "windsurf": {
38
+ "event": "pre_run_command",
39
+ "command": "...",
40
+ "show_output": true
41
+ }
42
+ }
43
+ }
44
+ ```
45
+
46
+ ### Platform differences
47
+
48
+ | Platform | Event name | Input key | Block mechanism |
49
+ |---|---|---|---|
50
+ | Claude Code | `PreToolUse` | `tool_input.command` | stdout JSON `{"decision":"block"}` |
51
+ | OpenAI Codex | `PreToolUse` | `tool_input.command` | stdout JSON `{"decision":"block"}` (same engine) |
52
+ | Windsurf | `pre_run_command` | `tool_info.command_line` | exit code `2` |
53
+
54
+ All hooks receive the tool input as JSON on stdin and run as a bash command.
55
+
56
+ ### How the installer uses this
57
+
58
+ - `platforms.claude` → merged into `.claude/settings.json` under `hooks.PreToolUse`
59
+ - `platforms.codex` → appended to `.codex/config.toml` under `[[hooks.PreToolUse]]`
60
+ - `platforms.windsurf` → merged into `.windsurf/hooks.json` under `hooks.pre_run_command`
61
+
62
+ Reinstalling is idempotent — the installer removes the previous triples-agentic entry before writing the new one.
63
+
64
+ ---
65
+
66
+ ## `*.md` — Text-based safety rules
67
+
68
+ Used for platforms that have no executable hook mechanism. The installer strips the frontmatter and injects the body as an always-applied rule.
69
+
70
+ ```markdown
71
+ ---
72
+ name: dangerous-commands-safety
73
+ description: Safety guardrails — never run dangerous commands without explicit user confirmation
74
+ platform: all
75
+ ---
76
+
77
+ ## Safety Guardrails
78
+
79
+ Never run these commands without explicit user confirmation:
80
+
81
+ ```
82
+
83
+ ### How the installer uses this
84
+
85
+ | Platform | Output |
86
+ |---|---|
87
+ | Cursor AI | `.cursor/rules/triples-safety.mdc` with `alwaysApply: true` |
88
+ | GitHub Copilot | `.github/instructions/triples-safety.instructions.md` with `applyTo: "**"` |
89
+
90
+ ---
91
+
92
+ ## Adding a new safety rule
93
+
94
+ 1. Edit the pattern list in the `command` field of `dangerous-commands.json` (all three platform sections).
95
+ 2. Add the human-readable description to `dangerous-commands.md`.
96
+ 3. Reinstall: `npx triples-agentic`.
97
+
98
+ ## Adding a new platform
99
+
100
+ 1. Add a `"<platform>"` key under `platforms` in each `.json` hook file.
101
+ 2. Add a loader function and settings writer in `src/bin/setup.js`.
102
+ 3. Call the settings writer from the platform's `install*` function.
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "dangerous-commands",
3
+ "description": "Block dangerous shell commands before execution",
4
+ "platforms": {
5
+ "claude": {
6
+ "event": "PreToolUse",
7
+ "matcher": "Bash",
8
+ "hooks": [
9
+ {
10
+ "type": "command",
11
+ "command": "cmd=$(jq -r '.tool_input.command // \"\"'); if echo \"$cmd\" | grep -qiE 'rm[[:space:]]+-rf|rm[[:space:]]+-fr|rm[[:space:]]+(-[a-z]*r[a-z]*[[:space:]]+-[a-z]*f|-[a-z]*f[a-z]*[[:space:]]+-[a-z]*r)|git[[:space:]]+reset[[:space:]]+--hard|git[[:space:]]+push[[:space:]]+(.*--force|-f[[:space:]])|git[[:space:]]+checkout[[:space:]]+--|git[[:space:]]+restore[[:space:]]+\\.|DROP[[:space:]]+(TABLE|DATABASE)|DELETE[[:space:]]+FROM[[:space:]]+[a-zA-Z_]+[[:space:]]*;|fastlane[[:space:]]+(deliver|supply)|gradlew[[:space:]]+.*publishBundle|xcrun[[:space:]]+altool|npm[[:space:]]+publish[[:space:]]|npx[[:space:]]+.*publish[[:space:]]'; then printf '{\"decision\":\"block\",\"reason\":\"Blocked dangerous command — review and run manually if intentional.\"}'; fi",
12
+ "statusMessage": "Checking for dangerous commands..."
13
+ }
14
+ ]
15
+ },
16
+ "codex": {
17
+ "event": "PreToolUse",
18
+ "matcher": "Bash",
19
+ "hooks": [
20
+ {
21
+ "type": "command",
22
+ "command": "cmd=$(jq -r '.tool_input.command // \"\"'); if echo \"$cmd\" | grep -qiE 'rm[[:space:]]+-rf|rm[[:space:]]+-fr|rm[[:space:]]+(-[a-z]*r[a-z]*[[:space:]]+-[a-z]*f|-[a-z]*f[a-z]*[[:space:]]+-[a-z]*r)|git[[:space:]]+reset[[:space:]]+--hard|git[[:space:]]+push[[:space:]]+(.*--force|-f[[:space:]])|git[[:space:]]+checkout[[:space:]]+--|git[[:space:]]+restore[[:space:]]+\\.|DROP[[:space:]]+(TABLE|DATABASE)|DELETE[[:space:]]+FROM[[:space:]]+[a-zA-Z_]+[[:space:]]*;|fastlane[[:space:]]+(deliver|supply)|gradlew[[:space:]]+.*publishBundle|xcrun[[:space:]]+altool|npm[[:space:]]+publish[[:space:]]|npx[[:space:]]+.*publish[[:space:]]'; then printf '{\"decision\":\"block\",\"reason\":\"Blocked dangerous command — review and run manually if intentional.\"}'; fi",
23
+ "statusMessage": "Checking for dangerous commands..."
24
+ }
25
+ ]
26
+ },
27
+ "windsurf": {
28
+ "event": "pre_run_command",
29
+ "command": "cmd=$(jq -r '.tool_info.command_line // \"\"' 2>/dev/null || echo \"\"); if echo \"$cmd\" | grep -qiE 'rm[[:space:]]+-rf|rm[[:space:]]+-fr|rm[[:space:]]+(-[a-z]*r[a-z]*[[:space:]]+-[a-z]*f|-[a-z]*f[a-z]*[[:space:]]+-[a-z]*r)|git[[:space:]]+reset[[:space:]]+--hard|git[[:space:]]+push[[:space:]]+(.*--force|-f[[:space:]])|git[[:space:]]+checkout[[:space:]]+--|git[[:space:]]+restore[[:space:]]+\\.|DROP[[:space:]]+(TABLE|DATABASE)|DELETE[[:space:]]+FROM[[:space:]]+[a-zA-Z_]+[[:space:]]*;|fastlane[[:space:]]+(deliver|supply)|gradlew[[:space:]]+.*publishBundle|xcrun[[:space:]]+altool|npm[[:space:]]+publish[[:space:]]|npx[[:space:]]+.*publish[[:space:]]'; then printf 'Blocked dangerous command — review and run manually if intentional.\\n' >&2; exit 2; fi",
30
+ "show_output": true
31
+ }
32
+ }
33
+ }
@@ -0,0 +1,18 @@
1
+ ---
2
+ name: dangerous-commands-safety
3
+ description: Safety guardrails — never run dangerous commands without explicit user confirmation
4
+ platform: all
5
+ ---
6
+
7
+ ## Safety Guardrails
8
+
9
+ Never run these commands without explicit user confirmation:
10
+
11
+ - **Filesystem**: `rm -rf`, `rm -fr`, any recursive force delete
12
+ - **Git destructive**: `git reset --hard`, `git checkout --`, `git restore .`
13
+ - **Git push force**: `git push --force`, `git push -f`
14
+ - **SQL destructive**: `DROP TABLE`, `DROP DATABASE`, `DELETE FROM <table>;`
15
+ - **Store publish**: `fastlane deliver`, `fastlane supply`, `gradlew publishBundle`, `xcrun altool`
16
+ - **Package publish**: `npm publish`, `npx ... publish`
17
+
18
+ Stop and ask the user for explicit confirmation before running any of the above.
@@ -0,0 +1,129 @@
1
+ # knowledge/
2
+
3
+ Domain expertise loaded by agents at runtime. Pure reference `.md` files — no trigger logic, no skills framework.
4
+
5
+ Agents declare which files to load via `<!-- knowledge: ... -->` metadata in their agent definition. The AI reads and applies these files as context when it activates.
6
+
7
+ ---
8
+
9
+ ## File format
10
+
11
+ Every knowledge file has YAML frontmatter followed by markdown content:
12
+
13
+ ```markdown
14
+ ---
15
+ name: api-design
16
+ description: REST and GraphQL API design conventions — URL structure, versioning, pagination, filtering, and documentation
17
+ ---
18
+
19
+ # API Design
20
+
21
+ ## REST URL Conventions
22
+
23
+ ```
24
+
25
+ | Field | Purpose |
26
+ |---|---|
27
+ | `name` | Slug used as the skill name when installed to Claude Code |
28
+ | `description` | One-line summary shown in the install banner and used as the skill trigger description |
29
+
30
+ The content is plain markdown — headings, bullet lists, code blocks. Write it as a reference document, not a tutorial.
31
+
32
+ ---
33
+
34
+ ## Directory structure
35
+
36
+ ```
37
+ knowledge/
38
+ ├── general/ Coding principles — loaded by all developer agents
39
+ │ ├── dry.md Don't Repeat Yourself
40
+ │ ├── kiss.md Keep It Simple
41
+ │ ├── yagni.md You Aren't Gonna Need It
42
+ │ ├── solid.md SOLID principles
43
+ │ ├── slap.md Single Level of Abstraction
44
+ │ ├── tdd.md Test-Driven Development
45
+ │ ├── fail-fast.md Validate at boundaries, surface errors early
46
+ │ ├── least-surprise.md Code behaves as readers expect
47
+ │ ├── boy-scout-rule.md Leave code cleaner than you found it
48
+ │ └── composition-over-inheritance.md
49
+
50
+ ├── planning/ Loaded by SeoYeon, JiWoo, YooYeon, NaKyoung
51
+ │ ├── orchestration.md Workflow sequencing, delegation, escalation
52
+ │ ├── prd-writing.md PRD structure, writing standards, anti-patterns
53
+ │ ├── prd-quality-gates.md PRD review checklist
54
+ │ ├── product-principles.md PM principles, prioritization frameworks
55
+ │ ├── product-prioritization.md
56
+ │ ├── rfc-writing.md RFC structure, ADR format, anti-patterns
57
+ │ ├── rfc-quality-gates.md RFC review checklist
58
+ │ ├── architecture-patterns.md System design, database selection, scalability
59
+ │ ├── architecture-database.md Database design and selection criteria
60
+ │ ├── architecture-security.md Security fundamentals for system design
61
+ │ ├── task-decomposition.md Task hierarchy, story mapping, readiness checklist
62
+ │ ├── task-readiness.md Task readiness criteria
63
+ │ └── estimation.md Fibonacci points, time estimation, planning poker
64
+
65
+ ├── web/
66
+ │ ├── frontend/ Loaded by YuBin
67
+ │ │ ├── frontend-components.md React/Vue/Angular patterns, component design
68
+ │ │ ├── frontend-state.md State management patterns
69
+ │ │ ├── frontend-performance.md Bundle size, rendering, lazy loading
70
+ │ │ ├── web-accessibility.md WCAG 2.1 AA, semantic HTML, ARIA
71
+ │ │ ├── web-performance.md LCP, CLS, Core Web Vitals
72
+ │ │ └── web-security.md CSP, XSS prevention, secure headers
73
+ │ └── backend/ Loaded by Kaede (api-design.md also loaded by Kotone)
74
+ │ ├── backend-structure.md Project layout, layered architecture
75
+ │ ├── backend-security.md Input validation, parameterized queries, secrets
76
+ │ ├── api-design.md REST/GraphQL conventions, versioning, pagination
77
+ │ └── api-security.md Auth, rate limiting, OWASP API top 10
78
+
79
+ ├── mobile/
80
+ │ ├── android/ Loaded by YeonJi
81
+ │ │ ├── android-architecture.md MVVM, Compose, Hilt, Navigation, Material 3
82
+ │ │ ├── android-platform.md Play Store, permissions, lifecycle
83
+ │ │ ├── kotlin-core.md Null safety, sealed classes, extension functions
84
+ │ │ └── kotlin-concurrency.md Coroutines, Flow, structured concurrency
85
+ │ ├── ios/ Loaded by SoHyun
86
+ │ │ ├── ios-architecture.md SwiftUI, MVVM, NavigationStack, Apple HIG
87
+ │ │ ├── ios-platform.md App Store, privacy manifest, safe areas
88
+ │ │ ├── swift-core.md Optionals, value types, async/await, protocols
89
+ │ │ └── swift-concurrency.md actors, async/await, Task, structured concurrency
90
+ │ └── flutter/ Loaded by Kotone
91
+ │ ├── flutter-architecture.md Riverpod, GoRouter, Material 3, widget design
92
+ │ ├── flutter-platform.md Play Store + App Store, platform channels
93
+ │ ├── dart-core.md Null safety, collections, classes, mixins
94
+ │ └── dart-async.md async/await, Future, Stream, Isolate
95
+
96
+ └── quality/ Loaded by Lynn and ShiOn
97
+ ├── testing-strategy.md Testing pyramid, shift-left, anti-patterns
98
+ ├── testing-types.md Unit, integration, E2E, exploratory definitions
99
+ ├── test-case-writing.md Test case structure, priority levels, quality gates
100
+ ├── test-case-quality.md Quality checklist for test case review
101
+ ├── qa-execution.md Execution process, bug report format, go/no-go criteria
102
+ └── qa-reporting.md QA report structure, metrics, defect classification
103
+ ```
104
+
105
+ ---
106
+
107
+ ## How knowledge gets installed
108
+
109
+ The installer copies each knowledge file to the target platform directory alongside the agent files:
110
+
111
+ | Platform | Installed path |
112
+ |---|---|
113
+ | Claude Code | `.claude/skills/knowledge/<group>/<file>.md` (existing frontmatter kept) |
114
+ | Cursor AI | `.cursor/rules/knowledge/<group>/<file>.mdc` (frontmatter rewritten for Cursor) |
115
+ | GitHub Copilot | `.github/instructions/knowledge/<group>/<file>.instructions.md` |
116
+ | OpenAI Codex | Inline section in `AGENTS.md` (frontmatter stripped) |
117
+ | Windsurf | Inline section in `.windsurfrules` (frontmatter stripped) |
118
+
119
+ ---
120
+
121
+ ## Adding a knowledge file
122
+
123
+ 1. Create a `.md` file in the appropriate subdirectory.
124
+ 2. Add frontmatter with `name` and `description`.
125
+ 3. Write the content as a reference document.
126
+ 4. Reference it in the agent's `<!-- knowledge: ... -->` metadata and add a line to its `## Knowledge` section.
127
+ 5. Reinstall: `npx triples-agentic`.
128
+
129
+ Knowledge files are **read-only reference** — they describe what to know, not what to do. Procedural steps belong in agent `## Skills` sections.
@@ -0,0 +1,13 @@
1
+ ---
2
+ name: boy-scout-rule
3
+ description: Boy Scout Rule — leave the code cleaner than you found it through small, incremental improvements
4
+ ---
5
+
6
+ # Boy Scout Rule
7
+
8
+ Leave the code cleaner than you found it.
9
+
10
+ - If you touch a file, fix the obvious issues nearby (rename a confusing variable, remove a dead comment)
11
+ - Do not let this justify scope creep — small, incremental improvements only
12
+ - Do not refactor code you do not understand yet
13
+ - A codebase that improves slightly with every PR never needs a big rewrite
@@ -0,0 +1,14 @@
1
+ ---
2
+ name: composition-over-inheritance
3
+ description: Favor composing behavior from small focused pieces over deep inheritance hierarchies
4
+ ---
5
+
6
+ # Composition Over Inheritance
7
+
8
+ Favor composing behavior from small, focused pieces over deep inheritance hierarchies.
9
+
10
+ - Inheritance couples subclass to superclass implementation details
11
+ - Composition lets you swap or combine behaviors at runtime
12
+ - Prefer interfaces/protocols + composition when multiple behaviors are needed
13
+ - Deep inheritance trees are hard to reason about — changes at the top ripple unpredictably
14
+ - A class that inherits from more than one level of hierarchy is a warning sign
@@ -0,0 +1,14 @@
1
+ ---
2
+ name: dry
3
+ description: DRY (Don't Repeat Yourself) — every piece of knowledge must have a single, unambiguous representation in the system
4
+ ---
5
+
6
+ # DRY — Don't Repeat Yourself
7
+
8
+ Every piece of knowledge must have a single, unambiguous representation in the system.
9
+
10
+ - Extract repeated logic into a named function, class, or module
11
+ - Repeated data belongs in a constant or configuration, not scattered literals
12
+ - Duplication of intent is worse than duplication of text — two functions that do the same thing but look different are the hardest to catch
13
+
14
+ **When NOT to apply:** Premature abstraction to avoid three similar-looking lines produces worse code than the duplication. Wait for a third repetition before extracting. Deduplication that crosses wrong boundaries creates tight coupling.
@@ -0,0 +1,13 @@
1
+ ---
2
+ name: fail-fast
3
+ description: Fail Fast — detect and surface errors as early and loudly as possible
4
+ ---
5
+
6
+ # Fail Fast
7
+
8
+ Detect and surface errors as early and loudly as possible.
9
+
10
+ - Validate inputs at system boundaries, not deep inside business logic
11
+ - Return or throw immediately on invalid state — don't carry partial state forward
12
+ - Assertions and guards at function entry are cheaper than debugging corrupted state later
13
+ - An error that surfaces at the point of cause is 10x easier to diagnose than one that surfaces two call frames later
@@ -0,0 +1,15 @@
1
+ ---
2
+ name: kiss
3
+ description: KISS (Keep It Simple, Stupid) — the simplest solution that works is correct; complexity must justify itself
4
+ ---
5
+
6
+ # KISS — Keep It Simple, Stupid
7
+
8
+ The simplest solution that works is correct. Complexity must justify itself.
9
+
10
+ - Prefer readable, obvious code over clever one-liners
11
+ - Avoid over-engineering for hypothetical future requirements
12
+ - If you need a comment to explain what the code does, the code is probably too complex
13
+ - Fewer moving parts = fewer failure modes
14
+
15
+ **Ask before adding complexity:** "Will this system actually need this in the next 3 months?" If no, don't build it.
@@ -0,0 +1,13 @@
1
+ ---
2
+ name: least-surprise
3
+ description: Principle of Least Surprise — code should behave in the way a reader would expect
4
+ ---
5
+
6
+ # Principle of Least Surprise
7
+
8
+ Code should behave in the way a reader would expect.
9
+
10
+ - Functions named `getUser` should not modify state
11
+ - A method that returns a list should never return `null` — return an empty list
12
+ - Avoid side effects in places where callers don't expect them (constructors, getters, equality checks)
13
+ - Consistent naming conventions matter: if `save()` persists to DB everywhere, it should do so everywhere
@@ -0,0 +1,29 @@
1
+ ---
2
+ name: slap
3
+ description: SLAP (Single Level of Abstraction Principle) — each function should operate at a single level of abstraction
4
+ ---
5
+
6
+ # SLAP — Single Level of Abstraction Principle
7
+
8
+ Each function should operate at a single level of abstraction.
9
+
10
+ ```
11
+ // Bad — mixes high-level orchestration with low-level detail
12
+ function processOrder(order) {
13
+ validateOrder(order);
14
+ const sql = `INSERT INTO orders (id, total) VALUES (${order.id}, ${order.total})`;
15
+ db.execute(sql);
16
+ sendEmail(order.user.email, 'Order confirmed');
17
+ }
18
+
19
+ // Good — consistent abstraction level
20
+ function processOrder(order) {
21
+ validateOrder(order);
22
+ saveOrder(order);
23
+ notifyUser(order);
24
+ }
25
+ ```
26
+
27
+ - If one line calls a named function and the next line contains raw SQL or DOM manipulation, the abstraction levels are mismatched
28
+ - Extract lower-level details into well-named helpers to restore consistency
29
+ - Consistent abstraction levels make a function readable top-to-bottom without context switches
@@ -0,0 +1,44 @@
1
+ ---
2
+ name: solid
3
+ description: SOLID principles for object-oriented design — SRP, OCP, LSP, ISP, DIP
4
+ ---
5
+
6
+ # SOLID Principles (Object-Oriented Design)
7
+
8
+ ## S — Single Responsibility Principle
9
+ A class (or module, or function) should have one reason to change.
10
+
11
+ - A class that handles both business logic and database access has two reasons to change
12
+ - Split responsibilities along the axis of change: what causes this to need updating?
13
+ - Small, focused units are easier to test, reuse, and rename
14
+
15
+ ## O — Open/Closed Principle
16
+ Open for extension, closed for modification.
17
+
18
+ - Add new behavior by adding new code, not by editing existing code
19
+ - Use polymorphism, strategy pattern, or composition to extend behavior
20
+ - Modifying existing code risks breaking existing behavior; adding new code does not
21
+
22
+ ## L — Liskov Substitution Principle
23
+ Subtypes must be substitutable for their base types without breaking the program.
24
+
25
+ - If `class B extends A`, then anywhere `A` is used, `B` must work correctly
26
+ - Violations: a subclass that throws on a method the base class supports, or returns a narrower result
27
+ - If you find yourself overriding a method to do nothing or throw, the inheritance hierarchy is wrong
28
+
29
+ ## I — Interface Segregation Principle
30
+ No client should be forced to depend on methods it does not use.
31
+
32
+ - Prefer several small, focused interfaces over one large general-purpose interface
33
+ - A class that implements a large interface but only needs 2 of 10 methods is a sign the interface should be split
34
+ - Applies to function parameters too: pass only what the callee actually needs
35
+
36
+ ## D — Dependency Inversion Principle
37
+ High-level modules should not depend on low-level modules. Both should depend on abstractions.
38
+
39
+ - Business logic should not import a specific database library directly — it should depend on a repository interface
40
+ - Makes high-level policy independent of implementation details
41
+ - Enables swapping implementations (e.g., real DB vs. in-memory for tests) without changing business logic
42
+
43
+ ## When to apply SOLID
44
+ SOLID is most valuable at module and service boundaries. Inside a small, private function, rigid SOLID application adds noise without benefit. Don't add abstractions until you have two concrete use cases.
@@ -0,0 +1,76 @@
1
+ ---
2
+ name: tdd
3
+ description: Test-Driven Development (TDD) — write a failing test first, then write the minimum code to make it pass, then refactor
4
+ ---
5
+
6
+ # TDD — Test-Driven Development
7
+
8
+ Write a failing test before writing any production code. Let the test drive the design.
9
+
10
+ ## The Red-Green-Refactor Cycle
11
+
12
+ 1. **Red** — write a test that describes the desired behavior. Run it. It must fail.
13
+ 2. **Green** — write the minimum code to make the test pass. No more.
14
+ 3. **Refactor** — clean up the code without changing behavior. Tests stay green.
15
+
16
+ Repeat for every new behavior.
17
+
18
+ ## Rules
19
+
20
+ - Never write production code without a failing test that justifies it
21
+ - Write only enough production code to make the current failing test pass
22
+ - Never refactor while red — only clean up when tests are passing
23
+ - One failing test at a time: don't write the next test until the current one is green
24
+
25
+ ## Why TDD produces better design
26
+
27
+ - Forces you to think about the interface before the implementation
28
+ - Code that is hard to test is a signal of tight coupling or unclear responsibilities — TDD surfaces this early
29
+ - The test suite becomes a living specification of what the system does
30
+ - Refactoring is safe when every behavior is covered — you move fast without breaking things
31
+
32
+ ## What a good TDD test looks like
33
+
34
+ ```
35
+ // Arrange — set up the inputs and context
36
+ // Act — call the unit under test
37
+ // Assert — verify the outcome
38
+
39
+ test('calculates order total with discount applied', () => {
40
+ const order = new Order([{ price: 100, qty: 2 }]);
41
+
42
+ const total = order.totalWithDiscount(0.1);
43
+
44
+ expect(total).toBe(180);
45
+ });
46
+ ```
47
+
48
+ - One concept per test
49
+ - Test name describes the behavior, not the implementation ("returns 180" not "calls applyDiscount")
50
+ - No logic in tests (no if/for) — tests should be trivially readable
51
+ - Tests are isolated: no shared mutable state between tests
52
+
53
+ ## TDD scope
54
+
55
+ | Level | What to TDD | Examples |
56
+ |---|---|---|
57
+ | Unit | Business logic, calculations, transformations | Services, utilities, domain models |
58
+ | Integration | Interactions between components | Repository + DB, API handler + service |
59
+ | E2E | Critical user flows | Login, checkout, core happy path |
60
+
61
+ TDD is most valuable at the unit and integration levels. E2E tests are expensive to write first — write them after the feature is built to lock in the happy path.
62
+
63
+ ## When NOT to apply TDD strictly
64
+
65
+ - **Exploratory / spike code** — when you don't yet know the shape of the solution, write the spike first, then delete it and TDD the real implementation
66
+ - **UI layout and styling** — visual behavior is better verified by snapshot or manual review
67
+ - **Third-party integrations** — write tests against your wrapper/adapter, not against the external API itself
68
+
69
+ ## TDD and refactoring
70
+
71
+ The refactor step is not optional. Green tests without refactoring accumulates design debt. After each green:
72
+
73
+ - Remove duplication (DRY)
74
+ - Rename for clarity
75
+ - Extract if a function is doing more than one thing (SRP)
76
+ - The test suite must still be fully green after every change
@@ -0,0 +1,12 @@
1
+ ---
2
+ name: yagni
3
+ description: YAGNI (You Aren't Gonna Need It) — do not implement something until it is actually required
4
+ ---
5
+
6
+ # YAGNI — You Aren't Gonna Need It
7
+
8
+ Do not implement something until it is actually required.
9
+
10
+ - No speculative features, hooks for future use, or "just in case" parameters
11
+ - Extension points and abstractions added before they are needed almost always get the shape wrong
12
+ - Dead code is a maintenance liability — it still needs to be read, reasoned about, and updated
@@ -0,0 +1,83 @@
1
+ ---
2
+ name: android-architecture
3
+ description: Android MVVM + Clean Architecture, Jetpack Compose patterns, Hilt DI, and Navigation Compose
4
+ ---
5
+
6
+ # Android Architecture
7
+
8
+ ## Architecture Pattern: MVVM + Clean Architecture
9
+
10
+ ```
11
+ UI Layer (Composable)
12
+ ↕ StateFlow / collect
13
+ ViewModel (state holder, no Android dependencies)
14
+ ↕ suspend functions / Flow
15
+ Repository (single data access layer)
16
+ ↕ API / Room / DataStore
17
+ ```
18
+
19
+ ## Jetpack Compose Rules
20
+
21
+ - Composables are stateless by default — pass state down, events up
22
+ - Use `remember` for UI-only ephemeral state (not business state)
23
+ - Hoist state to the lowest common ancestor that needs it
24
+ - Break large composables into smaller ones: if it doesn't fit on one screen, split it
25
+
26
+ ```kotlin
27
+ // Correct: stateless composable + hoisted state in ViewModel
28
+ @Composable
29
+ fun LoginScreen(
30
+ uiState: LoginUiState,
31
+ onEmailChanged: (String) -> Unit,
32
+ onLoginClick: () -> Unit,
33
+ ) { ... }
34
+
35
+ // Only at screen entry points (top-level routes)
36
+ @Composable
37
+ fun LoginRoute(viewModel: LoginViewModel = hiltViewModel()) {
38
+ LoginScreen(
39
+ uiState = viewModel.uiState.collectAsState().value,
40
+ onEmailChanged = viewModel::onEmailChanged,
41
+ onLoginClick = viewModel::login,
42
+ )
43
+ }
44
+ ```
45
+
46
+ ## Dependency Injection — Hilt
47
+
48
+ - `@HiltAndroidApp` on Application class
49
+ - `@AndroidEntryPoint` on Activities/Fragments that use injection
50
+ - `@HiltViewModel` for ViewModels
51
+ - Scopes: `@Singleton` for app-wide, `@ActivityScoped` for per-screen
52
+
53
+ ## Navigation — Navigation Compose
54
+
55
+ ```kotlin
56
+ // Define routes as a sealed hierarchy
57
+ sealed class Screen(val route: String) {
58
+ object Login : Screen("login")
59
+ data class Profile(val userId: String) : Screen("profile/{userId}")
60
+ }
61
+
62
+ // NavHost setup
63
+ NavHost(navController, startDestination = Screen.Login.route) {
64
+ composable(Screen.Login.route) { LoginRoute(navController) }
65
+ composable("profile/{userId}") { backStackEntry ->
66
+ ProfileRoute(userId = backStackEntry.arguments?.getString("userId")!!)
67
+ }
68
+ }
69
+ ```
70
+
71
+ Navigate from ViewModel using a sealed event/effect — never hold NavController in ViewModel.
72
+
73
+ ## Network — Retrofit + OkHttp
74
+
75
+ ```kotlin
76
+ @GET("users/{id}")
77
+ suspend fun getUser(@Path("id") id: String): UserDto
78
+
79
+ // Add logging interceptor for debug builds only
80
+ if (BuildConfig.DEBUG) {
81
+ addInterceptor(HttpLoggingInterceptor().apply { level = BODY })
82
+ }
83
+ ```