@rmrdeveloper/sideroom-pi 8.11.0 → 8.13.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 (64) hide show
  1. package/README.md +49 -5
  2. package/assets/artifacts/GUIDELINES_TEMPLATE.md +3 -3
  3. package/assets/visual-context/browser/INSTALL.md +69 -0
  4. package/assets/visual-context/browser/background.js +578 -0
  5. package/assets/visual-context/browser/content.js +198 -0
  6. package/assets/visual-context/browser/icons/README.md +9 -0
  7. package/assets/visual-context/browser/icons/icon-128.png +0 -0
  8. package/assets/visual-context/browser/icons/icon-16.png +0 -0
  9. package/assets/visual-context/browser/icons/icon-32.png +0 -0
  10. package/assets/visual-context/browser/icons/icon-48.png +0 -0
  11. package/assets/visual-context/browser/manifest.json +20 -0
  12. package/assets/visual-context/browser/popup.css +19 -0
  13. package/assets/visual-context/browser/popup.html +27 -0
  14. package/assets/visual-context/browser/popup.js +141 -0
  15. package/extensions/done/guard.ts +42 -37
  16. package/extensions/done/index.ts +3 -2
  17. package/extensions/done/model.ts +1 -5
  18. package/extensions/explain/guard.ts +13 -11
  19. package/extensions/explain/model.ts +2 -25
  20. package/extensions/guidelines/review.ts +31 -13
  21. package/extensions/jev/client.ts +22 -1
  22. package/extensions/jev/context.ts +36 -3
  23. package/extensions/jev/guard.ts +113 -34
  24. package/extensions/jev/model.ts +90 -12
  25. package/extensions/jev/workflow.ts +188 -0
  26. package/extensions/persona/execute.ts +4 -6
  27. package/extensions/persona/index.ts +3 -2
  28. package/extensions/persona/model.ts +1 -31
  29. package/extensions/persona/prompt.ts +3 -1
  30. package/extensions/shared/settle.ts +63 -13
  31. package/extensions/visual-context/bridge.ts +240 -0
  32. package/extensions/visual-context/broker.ts +292 -0
  33. package/extensions/visual-context/envelope.ts +34 -0
  34. package/extensions/visual-context/index.ts +328 -0
  35. package/extensions/visual-context/literal.ts +34 -0
  36. package/extensions/visual-context/markup.ts +104 -0
  37. package/extensions/visual-context/match.ts +222 -0
  38. package/extensions/visual-context/model.ts +180 -0
  39. package/extensions/visual-context/pairing.ts +114 -0
  40. package/extensions/visual-context/parse-astro.ts +166 -0
  41. package/extensions/visual-context/parse-html.ts +72 -0
  42. package/extensions/visual-context/parse-jsx.ts +157 -0
  43. package/extensions/visual-context/parse-svelte.ts +128 -0
  44. package/extensions/visual-context/parse-vue.ts +133 -0
  45. package/extensions/visual-context/session.ts +192 -0
  46. package/extensions/visual-context/source.ts +197 -0
  47. package/extensions/visual-context/ui.ts +57 -0
  48. package/package.json +16 -7
  49. package/skills/sideroom-architecture/SKILL.md +5 -3
  50. package/skills/sideroom-codebase-design/LICENSE.txt +21 -0
  51. package/skills/sideroom-codebase-design/SKILL.md +151 -0
  52. package/skills/sideroom-codebase-design/references/growth.md +62 -0
  53. package/skills/sideroom-domain-modeling/SKILL.md +1 -1
  54. package/skills/sideroom-domain-scaffold/SKILL.md +6 -4
  55. package/skills/sideroom-grill/SKILL.md +6 -4
  56. package/skills/sideroom-guidelines/SKILL.md +9 -7
  57. package/skills/sideroom-guidelines/references/languages/go.md +3 -3
  58. package/skills/sideroom-guidelines/references/languages/java.md +3 -3
  59. package/skills/sideroom-guidelines/references/languages/javascript.md +25 -3
  60. package/skills/sideroom-guidelines/references/languages/php-laravel.md +3 -3
  61. package/skills/sideroom-guidelines/references/languages/python.md +3 -3
  62. package/skills/sideroom-guidelines/references/languages/rust.md +3 -3
  63. package/skills/sideroom-guidelines/references/languages/typescript.md +27 -3
  64. package/skills/sideroom-persona/SKILL.md +15 -4
@@ -0,0 +1,151 @@
1
+ ---
2
+ name: sideroom-codebase-design
3
+ description: "Improve an existing codebase for long-term maintainability and scale. Use when asked to review code structure, find refactoring opportunities, reduce coupling, redesign module interfaces, improve testability, or prepare code for growing traffic, data, features, or teams. Survey the relevant code, prioritize evidenced friction, and design incremental improvements in text. Also use during a substantial refactor when module shape is the problem. Skip routine fixes, cosmetic cleanup, and unsettled product requirements; use sideroom-grill for those requirements."
4
+ license: MIT
5
+ metadata:
6
+ author: RMRdeveloper
7
+ version: "1.0"
8
+ ---
9
+
10
+ # Sideroom codebase design
11
+
12
+ Improve how an existing codebase absorbs change and known growth. Combine a
13
+ survey of architectural friction with concrete module design. Deliver prose,
14
+ Markdown tables, and code examples when useful. Do not generate diagrams,
15
+ graphs, images, SVG, Mermaid, HTML reports, or browser previews.
16
+
17
+ ## Activation and scope
18
+
19
+ Load for repository improvement, architecture reviews, module redesign,
20
+ refactoring, testability problems, or preparation for long-term growth. A user
21
+ does not need to name the skill. When a specific module is already chosen,
22
+ inspect its callers and dependencies and go straight to design; a whole-repo
23
+ survey is unnecessary.
24
+
25
+ Determine the requested outcome from the conversation:
26
+
27
+ - **Review:** investigate and recommend; do not refactor or create report files.
28
+ - **Design:** propose the shape of a selected improvement and its migration.
29
+ - **Implement:** carry out improvements within the already authorized scope,
30
+ including checks. Do not ask again for permission already given.
31
+
32
+ A review request does not authorize a rewrite. An implementation request does
33
+ not require pausing after every recommendation. Ask only about consequential
34
+ choices or missing facts that the user and repository have not settled.
35
+
36
+ ## Inspect before recommending
37
+
38
+ 1. Read project instructions, existing domain vocabulary (`CONTEXT.md`, or the
39
+ project's equivalent), and relevant ADRs. Respect existing contracts.
40
+ 2. Start with the area or pain point the user named. Otherwise, use available
41
+ history to find areas with repeated changes, fixes, or coordinated edits;
42
+ verify the friction in current code. History is a lead, not proof. If history
43
+ is absent or uninformative, follow central business flows and their tests.
44
+ 3. Trace representative behavior from entry point through domain logic and
45
+ persistence or external calls. Inspect real callers, configuration, error
46
+ handling, tests, and operational evidence available in scope.
47
+ 4. Identify what makes changes costly: knowledge duplicated across callers,
48
+ hidden ordering constraints, leaked internals, coupled release changes,
49
+ brittle test setup, resource bottlenecks, or unclear ownership. Cite actual
50
+ files and behavior. File length, folder count, or a missing pattern alone is
51
+ not an architectural finding.
52
+ 5. For growth concerns, load [references/growth.md](references/growth.md).
53
+ Separate verified constraints from assumptions. Missing production metrics
54
+ are a limitation, not permission to invent capacity claims.
55
+
56
+ ## Design principles
57
+
58
+ - A **module** presents an **interface** and hides an implementation. Its
59
+ interface includes everything callers must understand: inputs, outputs,
60
+ invariants, errors, ordering, configuration, and relevant resource behavior.
61
+ - Seek **depth**: useful behavior behind a small, coherent interface. Evaluate
62
+ the knowledge and coordination removed from callers, not implementation size.
63
+ Internally compose focused responsibilities; depth does not justify a god
64
+ object or combining unrelated reasons to change.
65
+ - Use the **deletion test**: if removing a wrapper eliminates complexity without
66
+ spreading obligations into callers, consider removing it. If callers must
67
+ each reconstruct important rules, the module is doing useful work.
68
+ - A **seam** is a point where behavior can be substituted; an **adapter** is a
69
+ concrete substitute there. Introduce seams for actual variation, isolation,
70
+ or testing needs. Production and test adapters can justify a seam; a generic
71
+ port with one implementation and no demonstrated need does not.
72
+ - Improve **locality** by keeping a business rule and its verification in a
73
+ clear place. Improve **leverage** by letting callers use that behavior without
74
+ learning its internal machinery. Explain these benefits in plain words.
75
+ - Preserve required validation, failure handling, compatibility, and supported
76
+ behavior. Simplicity is assessed against the full requirements.
77
+
78
+ Use the project's domain names in code. Explain necessary design terms once;
79
+ do not replace established vocabulary just to impose this glossary.
80
+
81
+ ## Prioritize and design
82
+
83
+ For each worthwhile candidate, state the evidence, current cost, proposed
84
+ change, expected benefit, migration cost, and confidence. Rank by avoided
85
+ defects and change cost, known growth needs, reach, effort, and reversibility.
86
+ Do not invent numerical scores or fill a quota of findings.
87
+
88
+ Use **Strong** for demonstrated friction with a defensible remedy, **Worth
89
+ exploring** when an important fact or experiment is still needed, and
90
+ **Speculative** for an unverified future concern. Speculative findings become
91
+ measurement or monitoring steps, not implementation tasks. Say when no
92
+ structural improvement is justified. Flag a conflicting ADR and explain the
93
+ new evidence before proposing to reopen it.
94
+
95
+ For the selected candidate:
96
+
97
+ 1. State the behavior and compatibility constraints that must survive.
98
+ 2. Describe the interface and show a representative caller when helpful. Name
99
+ inputs, outputs, errors, ownership, and ordering obligations. State which
100
+ complexity moves inside and which responsibilities remain separate.
101
+ 3. For a meaningful trade-off, compare genuinely different designs, including
102
+ keeping the current design when viable. Compare caller burden, change
103
+ locality, tests, operational cost, and migration; recommend one. Routine
104
+ improvements need no forced alternatives or subagents.
105
+ 4. Classify dependencies: computation can be tested directly; local resources
106
+ may use realistic test substitutes; owned remote services need contract and
107
+ failure coverage; external providers need controlled adapters and suitable
108
+ integration checks. Do not expose private implementation details only to
109
+ make tests easier, or claim mocks establish real provider behavior.
110
+ 5. Plan small coherent steps with their checks and rollback. Keep callers
111
+ working during transition, handle data migrations and mixed versions where
112
+ relevant, and remove temporary compatibility code only when safe.
113
+
114
+ ## Verification and skill composition
115
+
116
+ Test observable behavior through the interface used by callers. Preserve
117
+ regression coverage, failure cases, and compatibility. Replace redundant tests
118
+ only after equivalent behavior is covered and obsolete seams are removed;
119
+ do not delete tests merely because they inspect a smaller function. For scale
120
+ claims, identify the workload and measurement that would validate the benefit.
121
+
122
+ - Load `sideroom-guidelines` and applicable language guides before edits.
123
+ - Use `sideroom-architecture` for unresolved consequential contracts, data,
124
+ dependencies, or operational choices; reuse decisions already accepted.
125
+ - Use `sideroom-grill` when the product behavior itself is still open, and
126
+ `sideroom-domain-modeling` for actual naming conflicts. A design review does
127
+ not automatically launch an interview or write a glossary or ADR.
128
+ - In the TUI, use `sideroom_ask` for needed decisions. If no interactive question
129
+ tool is available, state the question in the conversation and continue only
130
+ independent investigation; never interpret tool failure as an answer.
131
+ - Apply `sideroom-persona` to the report and summary. Run the project's relevant
132
+ checks after implementation and report what they established.
133
+
134
+ ## Output
135
+
136
+ Lead with the highest-value recommendation or the finding that no change is
137
+ justified. A review contains prioritized candidates with file evidence,
138
+ before/after behavior in words, benefit, cost, confidence, and a recommended
139
+ next step. A design contains the proposed contract, trade-offs, migration,
140
+ verification, and unresolved facts. After implementation, report changes,
141
+ checks, and remaining limitations. Keep review results in the conversation
142
+ unless the user requests a document. No graphic or HTML artifact is produced.
143
+
144
+ ## Attribution
145
+
146
+ Adapted from Matt Pocock's
147
+ [codebase-design](https://github.com/mattpocock/skills/tree/main/skills/engineering/codebase-design)
148
+ and
149
+ [improve-codebase-architecture](https://github.com/mattpocock/skills/tree/main/skills/engineering/improve-codebase-architecture),
150
+ with Sideroom routing, incremental delivery, and growth assessment. The upstream
151
+ MIT notice is included in [LICENSE.txt](LICENSE.txt).
@@ -0,0 +1,62 @@
1
+ # Assess long-term growth
2
+
3
+ Read when the request concerns scaling, growing teams, or future evolution.
4
+ Choose the dimensions the current code and requested outcome actually touch.
5
+ Do not make the user complete a generic capacity questionnaire.
6
+
7
+ ## Establish the growth pressure
8
+
9
+ Distinguish three kinds of growth:
10
+
11
+ - **Behavior:** more features, business rules, integrations, and supported
12
+ versions. Inspect whether each addition requires coordinated changes across
13
+ unrelated files or duplicated decisions.
14
+ - **People:** more contributors, ownership boundaries, and concurrent changes.
15
+ Inspect contracts, dependency cycles, shared state, release coupling, and
16
+ whether a contributor can change one responsibility with bounded context.
17
+ - **Workload:** more requests, stored data, concurrency, or background jobs.
18
+ Inspect resource bounds, work per operation, contention, and failure behavior.
19
+
20
+ Use existing requirements, code, tests, measurements, incident notes, and
21
+ available history. State the current baseline, expected direction or target,
22
+ and time horizon when known. Ask only for missing figures that would change
23
+ the design choice. A code review can improve changeability without inventing
24
+ traffic forecasts or blocking on production access.
25
+
26
+ ## Check constraints, then choose mechanisms
27
+
28
+ | Evidence to inspect | Question to resolve |
29
+ | --- | --- |
30
+ | Unbounded lists, scans, buffers, or queries in a critical path | What bounds the work and memory as data grows? Is pagination, indexing, or batching justified by actual access patterns? |
31
+ | Shared mutable state, global locks, synchronous I/O, or long transactions | Where does concurrent work serialize, and which ownership or consistency guarantees must survive? |
32
+ | Retries, external calls, job queues, and duplicate events | What is bounded, cancellable, idempotent, or allowed to degrade? What happens when a dependency slows down? |
33
+ | Cross-module rules, coordinated edits, and shared releases | Which stable contract would let an ordinary feature change stay local? |
34
+ | Schema changes, public interfaces, and multiple deployed versions | How can old and new consumers coexist, and what makes migration or rollback safe? |
35
+ | Existing service boundaries and operations | Does distribution solve a measured constraint enough to pay for network failures, deployment, tracing, and coordination? |
36
+
37
+ Separate a code-level risk from a measured bottleneck. For example, an unbounded
38
+ query is observable in code, but its production latency impact needs a known
39
+ dataset and workload. A static review alone does not prove a capacity limit.
40
+
41
+ Do not default to microservices, queues, caches, plugin systems, or generic
42
+ repositories. Compare a simpler change inside the existing deployment first.
43
+ Prefer an evolution path with explicit contracts and small migrations over
44
+ building unused capabilities. A user's known growth requirement counts as a
45
+ real need, even before the traffic arrives.
46
+
47
+ ## Make the recommendation falsifiable
48
+
49
+ For a proposed scale improvement, state:
50
+
51
+ - The observed constraint and the evidence supporting it.
52
+ - The workload, data shape, or development scenario that matters.
53
+ - The mechanism expected to help and its cost or new failure mode.
54
+ - The relevant check: behavioral regression, concurrency test, query plan,
55
+ representative load measurement, or evidence that fewer callers must change.
56
+ - The success criterion supplied by requirements or established baseline.
57
+ If missing, label it unresolved instead of inventing an improvement percentage.
58
+
59
+ Organize longer work as **now**, **next**, and **when triggered**. Each later
60
+ step names the growth event or measurement that would justify it. Include
61
+ dependency order, transition risks, and rollback for the proposed migration.
62
+ Do not turn hypothetical concerns into a backlog of mandatory refactors.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: sideroom-domain-modeling
3
- description: "Resolve domain-language conflicts and naming decisions. Use when terms are ambiguous, overloaded, or used inconsistently; when deciding what belongs in CONTEXT.md; or when a domain choice may need an ADR. Use for one or a few terms, not for simply reading CONTEXT.md, scanning an entire repository, or reshaping modules."
3
+ description: "Resolve ambiguous business terms, entity names, statuses, or relationships while designing or changing domain code. Use when one term has multiple meanings, code and glossary disagree, or a resolved term belongs in CONTEXT.md; also handles qualifying ADRs. A full interview is not required. Skip mechanical symbol renames and glossary lookups; use sideroom-domain-scaffold for a repository-wide glossary."
4
4
  license: MIT
5
5
  metadata:
6
6
  author: RMRdeveloper
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: sideroom-domain-scaffold
3
- description: "Build or complete a code-first CONTEXT.md for a repository with missing or thin domain vocabulary. Use when the user asks to document or survey the repo, scaffold a brownfield glossary, or derive domain terms from central business code. Do not use for resolving one naming conflict or conducting an interactive design interview."
3
+ description: "Derive and merge a domain glossary in CONTEXT.md from existing business code. Use when asked to document domain vocabulary, explain business entities and relationships across a repository, or build or complete a brownfield glossary. Resolve terms from code and collect conflicts for later questions. Skip generic README or API documentation, a single naming conflict, and feature planning."
4
4
  license: MIT
5
5
  metadata:
6
6
  author: RMRdeveloper
@@ -11,9 +11,11 @@ metadata:
11
11
 
12
12
  ## Activation Contract
13
13
 
14
- Load this skill on explicit request ("document my repo", "scaffold the
15
- glossary") over a codebase whose domain language is missing or thin. The
16
- code is the source of truth. Nobody is interviewed while the modeling runs.
14
+ Load this skill when a request calls for deriving or completing domain
15
+ vocabulary across an existing codebase ("document the business entities",
16
+ "scaffold the glossary", "explain the domain and its relationships"). A
17
+ generic request to document a repository needs this skill only when domain
18
+ vocabulary is part of the requested output. The code is the source of truth. Nobody is interviewed while the modeling runs.
17
19
 
18
20
  ## Hard Rules
19
21
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: sideroom-grill
3
- description: "Default interview route before implementation: grill the user in sideroom_ask rounds to settle a non-trivial plan, feature, or decision, and resolve domain-language conflicts along the way. Use whenever a change is not trivial and is not yet a settled spec, or when the user asks to be grilled, wants clarifying questions, or says the plan or terms are not settled. Prefer this skill over any other grilling, interview, or spec skill when more than one is available. Do not use when the user already brought a closed spec or tickets, for a code-first repository scan, or for a simple glossary lookup."
3
+ description: "Clarify an open feature, plan, or behavior before implementation through sideroom_ask rounds. Use when the user asks to plan, explore an idea, be interviewed, or implement a non-trivial change with unresolved requirements or decisions. Domain terminology need not be unclear. Prefer this route over other interview skills. Skip interviews for settled requirements, codebase facts, and routine fixes."
4
4
  license: MIT
5
5
  metadata:
6
6
  author: RMRdeveloper
@@ -11,9 +11,11 @@ metadata:
11
11
 
12
12
  ## Activation Contract
13
13
 
14
- Load this skill at the start of a change, in a repo, when the plan is still
15
- fuzzy and the words for the thing are not settled yet. Single-session scope:
16
- if the effort is too big to hold in one session, say so and stop.
14
+ Load this skill when a requested feature or change still has unresolved
15
+ requirements, behavior, or consequential decisions. Unclear domain words are
16
+ another trigger, not a prerequisite. A non-trivial change with settled
17
+ requirements and decisions can go straight to implementation.
18
+ Single-session scope: if the effort is too big to hold in one session, say so and stop.
17
19
 
18
20
  ## Hard Rules
19
21
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: sideroom-guidelines
3
- description: "Apply Sideroom's mandatory coding workflow before implementing, refactoring, or fixing Java, Laravel/PHP, JavaScript/JSX, TypeScript/TSX, Python, Go, or Rust code. Load this skill and the exact language guide before mutation. Do not use for unrelated prose or domain-only discussions."
3
+ description: "Follow the mandatory coding workflow before any write or edit, including bug fixes, features, refactors, tests, configuration, and documentation edits. Read the complete skill first; also read the exact language guide for Java, PHP/Laravel, JavaScript/JSX, TypeScript/TSX, Python, Go, or Rust targets. Discussion or read-only investigation alone does not require loading it."
4
4
  license: MIT
5
5
  metadata:
6
6
  author: RMRdeveloper
@@ -15,7 +15,7 @@ Load this whole skill with `read`, without `offset` or `limit`, before the first
15
15
 
16
16
  ## Hard Rules
17
17
 
18
- - Treat every rule in the loaded language guide as mandatory for changed code.
18
+ - Apply the loaded guide to changed code in the context of the full user requirements and established project contracts. Architectural rules require demonstrated evidence; KISS, DRY, and YAGNI never justify omitting requested behavior, required error handling, compatibility, or meaningful tests.
19
19
  - Do not write or edit until exact full-file reads of the required packaged paths succeed; partial reads and same-named files do not count.
20
20
  - Do not bypass the gate with Bash, a subprocess, or another mutation tool.
21
21
  - Do not load language guides unrelated to files being changed.
@@ -38,8 +38,8 @@ Load this whole skill with `read`, without `offset` or `limit`, before the first
38
38
 
39
39
  1. Read this complete file from its packaged path before any mutation.
40
40
  2. Fully read the matching packaged language guide, if the target has a supported extension.
41
- 3. Implement the smallest change that satisfies the current requirement.
42
- 4. Review every changed unit against the loaded guide.
41
+ 3. Implement a focused change that satisfies all current requirements and preserves required existing behavior.
42
+ 4. Review the changes introduced by this run against the loaded guide; fix demonstrated violations caused by the change without refactoring unrelated code.
43
43
  5. Run the relevant formatter, linter, type checks, and tests before finishing.
44
44
 
45
45
  ## Do / Don't
@@ -50,9 +50,9 @@ Load this whole skill with `read`, without `offset` or `limit`, before the first
50
50
  | Early return on bad input | Pyramid `if/else` nesting |
51
51
  | Explicit error, fail now | Fallbacks that hide the real failure |
52
52
  | One responsibility per unit | Validate + transform + persist + notify together |
53
- | Extract when duplication repeats | Abstract before a second real use |
54
- | Simplest solution for the current problem | Layers, hooks, or config "just in case" |
55
- | Build only what is needed today | Fields or branches for a future case |
53
+ | Extract for real duplication, a present responsibility, or testability | Abstract only for hypothetical future reuse |
54
+ | Simplest design that satisfies the full requirements | Omit necessary structure to minimize code |
55
+ | Implement current requirements and established contracts completely | Add capabilities only for hypothetical future cases |
56
56
  | Compose small focused units | Deep inheritance for unrelated behavior |
57
57
  | Talk only to immediate collaborators | Reach through another object's internals |
58
58
  | A function either does or returns, not both | Side effects inside a getter |
@@ -68,6 +68,8 @@ Load this whole skill with `read`, without `offset` or `limit`, before the first
68
68
  | Depend on ports where variation is real | Couple a use case to a concrete implementation |
69
69
  | Comments only for non-obvious intent | Narration, noise, or stale TODOs |
70
70
 
71
+ For JavaScript and TypeScript, a function with 3 or more parameters uses one object destructured in the parameter list, unless an external or public compatibility contract fixes the signature. See the language guide for examples.
72
+
71
73
  ## Output Contract
72
74
 
73
75
  Changed code follows every applicable rule in the loaded complete guide. The final response names the validation run and any check that could not run. No extra files, layers, comments, or bypass mutations unless the requirement needs them.
@@ -237,7 +237,7 @@ func create(input ValidatedInput) (User, error) {
237
237
 
238
238
  ### 12. DRY (real duplication only)
239
239
 
240
- RULE: Extract when at least 2 of 3 hold: (a) the logic appears 3+ times, (b) a future rule change would need to touch all occurrences at once, (c) the copies represent the same domain concept. Do not extract on the first or second occurrence, and do not extract look-alike code that belongs to different concepts (a user's email validation vs a vendor's) — they will diverge.
240
+ RULE: Extract when at least 2 of 3 hold: (a) the logic appears 3+ times, (b) a future rule change would need to touch all occurrences at once, (c) the copies represent the same domain concept. Do not extract solely to anticipate reuse on the first or second occurrence, and do not extract look-alike code that belongs to different concepts (a user's email validation vs a vendor's) — they will diverge. Extraction for a present responsibility, clear contract, or testability is valid even with one caller.
241
241
 
242
242
  ```go
243
243
  // bad — extracted after one use
@@ -253,7 +253,7 @@ func normalizeTicketStatus(status string) TicketStatus {
253
253
 
254
254
  ### 13. KISS
255
255
 
256
- RULE: Ship the simplest solution for the current, real requirement. No configurability, hooks, or layers added "just in case."
256
+ RULE: Choose the simplest design that fully satisfies the current requirements and preserves required behavior. Avoid configurability, hooks, or layers without a demonstrated need; do not remove necessary structure just to reduce code size.
257
257
 
258
258
  ```go
259
259
  // bad
@@ -269,7 +269,7 @@ func formatPrice(value float64) string {
269
269
 
270
270
  ### 14. YAGNI
271
271
 
272
- RULE: Don't add fields, params, or branches for a use case that hasn't arrived. (Differs from KISS: KISS simplifies the chosen solution; YAGNI stops you building the unrequested one.)
272
+ RULE: Avoid capabilities for hypothetical future use cases without evidence. User requirements, established project contracts, required error handling, compatibility, and meaningful tests are current needs, not speculation. Never use YAGNI to omit them or remove existing supported behavior. Apply it to the proposed change, not as a reason to refactor unrelated code.
273
273
 
274
274
  ```go
275
275
  // bad
@@ -161,7 +161,7 @@ User create(ValidatedUser input) { User user = normalizer.normalize(input); repo
161
161
 
162
162
  ### 12. DRY (real duplication only)
163
163
 
164
- RULE: Extract when at least 2 of 3 hold: (a) the logic appears 3+ times, (b) a future rule change would need to touch all occurrences at once, (c) the copies represent the same domain concept. Do not extract on the first or second occurrence, and do not extract look-alike code that belongs to different concepts (a user's email validation vs a vendor's) — they will diverge.
164
+ RULE: Extract when at least 2 of 3 hold: (a) the logic appears 3+ times, (b) a future rule change would need to touch all occurrences at once, (c) the copies represent the same domain concept. Do not extract solely to anticipate reuse on the first or second occurrence, and do not extract look-alike code that belongs to different concepts (a user's email validation vs a vendor's) — they will diverge. Extraction for a present responsibility, clear contract, or testability is valid even with one caller.
165
165
 
166
166
  ```java
167
167
  // bad — extracted after one real use
@@ -172,7 +172,7 @@ TicketStatus normalizeTicketStatus(String status) { return TicketStatus.parse(st
172
172
 
173
173
  ### 13. KISS
174
174
 
175
- RULE: Ship the simplest solution for the current, real requirement. No configurability, hooks, or layers added "just in case."
175
+ RULE: Choose the simplest design that fully satisfies the current requirements and preserves required behavior. Avoid configurability, hooks, or layers without a demonstrated need; do not remove necessary structure just to reduce code size.
176
176
 
177
177
  ```java
178
178
  // bad
@@ -183,7 +183,7 @@ String formatPrice(BigDecimal value) { return "$" + value.setScale(2); }
183
183
 
184
184
  ### 14. YAGNI
185
185
 
186
- RULE: Don't add fields, params, or branches for a use case that hasn't arrived. (Differs from KISS: KISS simplifies the chosen solution; YAGNI stops you building the unrequested one.)
186
+ RULE: Avoid capabilities for hypothetical future use cases without evidence. User requirements, established project contracts, required error handling, compatibility, and meaningful tests are current needs, not speculation. Never use YAGNI to omit them or remove existing supported behavior. Apply it to the proposed change, not as a reason to refactor unrelated code.
187
187
 
188
188
  ```java
189
189
  // bad
@@ -249,7 +249,7 @@ async function createUser(userInput) {
249
249
 
250
250
  ### 12. DRY (real duplication only)
251
251
 
252
- RULE: Extract when at least 2 of 3 hold: (a) the logic appears 3+ times, (b) a future rule change would need to touch all occurrences at once, (c) the copies represent the same domain concept. Do not extract on the first or second occurrence, or extract look-alike code from different concepts.
252
+ RULE: Extract when at least 2 of 3 hold: (a) the logic appears 3+ times, (b) a future rule change would need to touch all occurrences at once, (c) the copies represent the same domain concept. Do not extract solely to anticipate reuse on the first or second occurrence, or extract look-alike code from different concepts. Extraction for a present responsibility, clear contract, or testability is valid even with one caller.
253
253
 
254
254
  ```js
255
255
  // bad — extracted after one use
@@ -264,7 +264,7 @@ function normalizeTicketStatus(status) {
264
264
 
265
265
  ### 13. KISS
266
266
 
267
- RULE: Ship the simplest solution for the current, real requirement. No configurability, hooks, or layers added "just in case."
267
+ RULE: Choose the simplest design that fully satisfies the current requirements and preserves required behavior. Avoid configurability, hooks, or layers without a demonstrated need; do not remove necessary structure just to reduce code size.
268
268
 
269
269
  ```js
270
270
  // bad
@@ -279,7 +279,7 @@ function formatPrice(value) {
279
279
 
280
280
  ### 14. YAGNI
281
281
 
282
- RULE: Don't add fields, params, or branches for a use case that hasn't arrived. (KISS simplifies the chosen solution; YAGNI stops you building the unrequested one.)
282
+ RULE: Avoid capabilities for hypothetical future use cases without evidence. User requirements, established project contracts, required error handling, compatibility, and meaningful tests are current needs, not speculation. Never use YAGNI to omit them or remove existing supported behavior. Apply it to the proposed change, not as a reason to refactor unrelated code.
283
283
 
284
284
  ```js
285
285
  // bad
@@ -382,3 +382,25 @@ setInterval(checkPaymentStatus, 5_000);
382
382
  **When in doubt:** fail fast, keep it flat, keep it small.
383
383
 
384
384
  **Enforcement note:** rules 1–2 are mechanical and should be backed by a JavaScript formatter/linter. Rules 3–10 are structural checks. Rules 11–19 require review judgment.
385
+
386
+ ## Language-specific conventions
387
+
388
+ ### Destructured function parameters
389
+
390
+ When a function would take 3 or more parameters, accept one object and destructure its named properties in the parameter list. Count optional and defaulted parameters toward the threshold. Functions with 1 or 2 parameters may keep positional parameters.
391
+
392
+ Keep signatures imposed by external APIs, framework callbacks, overrides, or public compatibility contracts; use a destructured internal helper when it makes the implementation clearer. When changing a signature you own, update its callers together. Do not rewrite unrelated functions only to satisfy this convention.
393
+
394
+ ```js
395
+ // bad
396
+ function createInvoice(order, currency, dueDate) {
397
+ return { items: order.items, total: order.total, currency, dueDate };
398
+ }
399
+
400
+ // good
401
+ function createInvoice({ order, currency, dueDate }) {
402
+ return { items: order.items, total: order.total, currency, dueDate };
403
+ }
404
+
405
+ createInvoice({ order, currency: 'USD', dueDate });
406
+ ```
@@ -153,7 +153,7 @@ function create(ValidatedUser $input): User { $user = $this->normalizer->normali
153
153
 
154
154
  ### 12. DRY (real duplication only)
155
155
 
156
- RULE: Extract when at least 2 of 3 hold: (a) the logic appears 3+ times, (b) a future rule change would need to touch all occurrences at once, (c) the copies represent the same domain concept. Do not extract on the first or second occurrence, or extract look-alike code from different concepts.
156
+ RULE: Extract when at least 2 of 3 hold: (a) the logic appears 3+ times, (b) a future rule change would need to touch all occurrences at once, (c) the copies represent the same domain concept. Do not extract solely to anticipate reuse on the first or second occurrence, or extract look-alike code from different concepts. Extraction for a present responsibility, clear contract, or testability is valid even with one caller.
157
157
 
158
158
  ```php
159
159
  // bad — extracted after one use
@@ -164,7 +164,7 @@ function normalizeTicketStatus(string $status): TicketStatus { return TicketStat
164
164
 
165
165
  ### 13. KISS
166
166
 
167
- RULE: Ship the simplest solution for the current, real requirement. No configurability, hooks, or layers added "just in case."
167
+ RULE: Choose the simplest design that fully satisfies the current requirements and preserves required behavior. Avoid configurability, hooks, or layers without a demonstrated need; do not remove necessary structure just to reduce code size.
168
168
 
169
169
  ```php
170
170
  // bad
@@ -175,7 +175,7 @@ function formatPrice(float $value): string { return '$'.number_format($value, 2)
175
175
 
176
176
  ### 14. YAGNI
177
177
 
178
- RULE: Don't add fields, params, or branches for a use case that hasn't arrived. (KISS simplifies the chosen solution; YAGNI stops you building the unrequested one.)
178
+ RULE: Avoid capabilities for hypothetical future use cases without evidence. User requirements, established project contracts, required error handling, compatibility, and meaningful tests are current needs, not speculation. Never use YAGNI to omit them or remove existing supported behavior. Apply it to the proposed change, not as a reason to refactor unrelated code.
179
179
 
180
180
  ```php
181
181
  // bad
@@ -205,7 +205,7 @@ def create_user(validated_payload, repository):
205
205
 
206
206
  ### 12. DRY (real duplication only)
207
207
 
208
- RULE: Extract when at least 2 of 3 hold: (a) the logic appears 3+ times, (b) a future rule change would need to touch all occurrences at once, (c) the copies represent the same domain concept. Do not extract on the first or second occurrence, and do not extract look-alike code that belongs to different concepts (a user's email validation vs a vendor's) — they will diverge.
208
+ RULE: Extract when at least 2 of 3 hold: (a) the logic appears 3+ times, (b) a future rule change would need to touch all occurrences at once, (c) the copies represent the same domain concept. Do not extract solely to anticipate reuse on the first or second occurrence, and do not extract look-alike code that belongs to different concepts (a user's email validation vs a vendor's) — they will diverge. Extraction for a present responsibility, clear contract, or testability is valid even with one caller.
209
209
 
210
210
  ```python
211
211
  # bad — extracted after one real use
@@ -218,7 +218,7 @@ def normalize_ticket_status(status):
218
218
 
219
219
  ### 13. KISS
220
220
 
221
- RULE: Ship the simplest solution for the current, real requirement. No configurability, hooks, or layers added "just in case."
221
+ RULE: Choose the simplest design that fully satisfies the current requirements and preserves required behavior. Avoid configurability, hooks, or layers without a demonstrated need; do not remove necessary structure just to reduce code size.
222
222
 
223
223
  ```python
224
224
  # bad
@@ -231,7 +231,7 @@ def format_price(value):
231
231
 
232
232
  ### 14. YAGNI
233
233
 
234
- RULE: Don't add fields, params, or branches for a use case that hasn't arrived. (Differs from KISS: KISS simplifies the chosen solution; YAGNI stops you building the unrequested one.)
234
+ RULE: Avoid capabilities for hypothetical future use cases without evidence. User requirements, established project contracts, required error handling, compatibility, and meaningful tests are current needs, not speculation. Never use YAGNI to omit them or remove existing supported behavior. Apply it to the proposed change, not as a reason to refactor unrelated code.
235
235
 
236
236
  ```python
237
237
  # bad
@@ -155,7 +155,7 @@ fn create(input: ValidatedInput, repo: &impl Repo) -> Result<User> { let user =
155
155
 
156
156
  ### 12. DRY (real duplication only)
157
157
 
158
- RULE: Extract when at least 2 of 3 hold: (a) the logic appears 3+ times, (b) a future rule change would need to touch all occurrences at once, (c) the copies represent the same domain concept. Do not extract on the first or second occurrence, or extract look-alike code from different concepts.
158
+ RULE: Extract when at least 2 of 3 hold: (a) the logic appears 3+ times, (b) a future rule change would need to touch all occurrences at once, (c) the copies represent the same domain concept. Do not extract solely to anticipate reuse on the first or second occurrence, or extract look-alike code from different concepts. Extraction for a present responsibility, clear contract, or testability is valid even with one caller.
159
159
 
160
160
  ```rust
161
161
  // bad — extracted after one use
@@ -166,7 +166,7 @@ fn normalize_ticket_status(status: &str) -> Result<TicketStatus> { status.trim()
166
166
 
167
167
  ### 13. KISS
168
168
 
169
- RULE: Ship the simplest solution for the current, real requirement. No configurability, hooks, or layers added "just in case."
169
+ RULE: Choose the simplest design that fully satisfies the current requirements and preserves required behavior. Avoid configurability, hooks, or layers without a demonstrated need; do not remove necessary structure just to reduce code size.
170
170
 
171
171
  ```rust
172
172
  // bad
@@ -177,7 +177,7 @@ fn format_price(value: f64) -> String { format!("${value:.2}") }
177
177
 
178
178
  ### 14. YAGNI
179
179
 
180
- RULE: Don't add fields, params, or branches for a use case that hasn't arrived. (KISS simplifies the chosen solution; YAGNI stops you building the unrequested one.)
180
+ RULE: Avoid capabilities for hypothetical future use cases without evidence. User requirements, established project contracts, required error handling, compatibility, and meaningful tests are current needs, not speculation. Never use YAGNI to omit them or remove existing supported behavior. Apply it to the proposed change, not as a reason to refactor unrelated code.
181
181
 
182
182
  ```rust
183
183
  // bad
@@ -154,7 +154,7 @@ async function create(input: ValidatedUser): Promise<User> { const user = normal
154
154
 
155
155
  ### 12. DRY (real duplication only)
156
156
 
157
- RULE: Extract when at least 2 of 3 hold: (a) the logic appears 3+ times, (b) a future rule change would need to touch all occurrences at once, (c) the copies represent the same domain concept. Do not extract on the first or second occurrence, or extract look-alike code from different concepts.
157
+ RULE: Extract when at least 2 of 3 hold: (a) the logic appears 3+ times, (b) a future rule change would need to touch all occurrences at once, (c) the copies represent the same domain concept. Do not extract solely to anticipate reuse on the first or second occurrence, or extract look-alike code from different concepts. Extraction for a present responsibility, clear contract, or testability is valid even with one caller.
158
158
 
159
159
  ```ts
160
160
  // bad — extracted after one use
@@ -165,7 +165,7 @@ const normalizeTicketStatus = (status: string): TicketStatus => parseTicketStatu
165
165
 
166
166
  ### 13. KISS
167
167
 
168
- RULE: Ship the simplest solution for the current, real requirement. No configurability, hooks, or layers added "just in case."
168
+ RULE: Choose the simplest design that fully satisfies the current requirements and preserves required behavior. Avoid configurability, hooks, or layers without a demonstrated need; do not remove necessary structure just to reduce code size.
169
169
 
170
170
  ```ts
171
171
  // bad
@@ -176,7 +176,7 @@ function formatPrice(value: number): string { return `$${value.toFixed(2)}`; }
176
176
 
177
177
  ### 14. YAGNI
178
178
 
179
- RULE: Don't add fields, params, or branches for a use case that hasn't arrived. (KISS simplifies the chosen solution; YAGNI stops you building the unrequested one.)
179
+ RULE: Avoid capabilities for hypothetical future use cases without evidence. User requirements, established project contracts, required error handling, compatibility, and meaningful tests are current needs, not speculation. Never use YAGNI to omit them or remove existing supported behavior. Apply it to the proposed change, not as a reason to refactor unrelated code.
180
180
 
181
181
  ```ts
182
182
  // bad
@@ -247,3 +247,27 @@ setInterval(checkPaymentStatus, 5_000);
247
247
  **When in doubt:** fail fast, keep it flat, keep it small.
248
248
 
249
249
  **Enforcement note:** rules 1–2 are mechanical and should be backed by TypeScript formatting or linting. Rules 3–10 are structural checks. Rules 11–19 require review judgment.
250
+
251
+ ## Language-specific conventions
252
+
253
+ ### Destructured function parameters
254
+
255
+ When a function would take 3 or more parameters, accept one object and destructure its named properties in the parameter list. Count optional and defaulted parameters toward the threshold. Functions with 1 or 2 parameters may keep positional parameters. In TypeScript, type the object with a named type or interface.
256
+
257
+ Keep signatures imposed by external APIs, framework callbacks, overrides, or public compatibility contracts; use a destructured internal helper when it makes the implementation clearer. When changing a signature you own, update its callers together. Do not rewrite unrelated functions only to satisfy this convention.
258
+
259
+ ```ts
260
+ // bad
261
+ function createInvoice(order: Order, currency: string, dueDate: Date): Invoice {
262
+ return { items: order.items, total: order.total, currency, dueDate };
263
+ }
264
+
265
+ // good
266
+ type InvoiceInput = { order: Order; currency: string; dueDate: Date };
267
+
268
+ function createInvoice({ order, currency, dueDate }: InvoiceInput): Invoice {
269
+ return { items: order.items, total: order.total, currency, dueDate };
270
+ }
271
+
272
+ createInvoice({ order, currency: 'USD', dueDate });
273
+ ```