diff --git a/plugins-main/.cursor-plugin/marketplace.json b/plugins-main/.cursor-plugin/marketplace.json index 4c2f963..b8b8639 100644 --- a/plugins-main/.cursor-plugin/marketplace.json +++ b/plugins-main/.cursor-plugin/marketplace.json @@ -518,6 +518,11 @@ "source": "third_party/workday", "description": "Look up workers, organizations, time off, payroll, and recruiting data in Workday." }, + { + "name": "whatsapp-business", + "source": "third_party/whatsapp-business", + "description": "Send messages and manage templates, contacts, and phone numbers in WhatsApp Business." + }, { "name": "square", "source": "third_party/square", diff --git a/plugins-main/README.md b/plugins-main/README.md index 61eca8b..b42a644 100644 --- a/plugins-main/README.md +++ b/plugins-main/README.md @@ -95,6 +95,7 @@ Official Cursor plugins for popular developer tools, frameworks, and SaaS produc | `shopify-store` | [Shopify](third_party/shopify-store/) | Cursor | Integrations | Connect your Shopify store so Grok can answer questions about products, orders, customers, inventory, and sales. | | `quickbooks-online` | [QuickBooks Online](third_party/quickbooks-online/) | Cursor | Integrations | Read invoices, bills, expenses, customers, accounts, and financial reports. | | `workday` | [Workday](third_party/workday/) | Cursor | Integrations | Look up workers, organizations, time off, payroll, and recruiting data in Workday. | +| `whatsapp-business` | [WhatsApp Business](third_party/whatsapp-business/) | Cursor | Integrations | Send messages and manage templates, contacts, and phone numbers in WhatsApp Business. | | `square` | [Square](third_party/square/) | Cursor | Integrations | Work with payments, orders, catalog, customers, and invoices. | | `tailscale` | [Tailscale](third_party/tailscale/) | Cursor | Integrations | Let Grok Bot reach MCP servers on your private Tailscale network. Sign in to Tailscale to connect your tailnet; Grok Bot joins it as one tagged device and only reaches the hosts you grant to tag:grokbot. | | `highlevel` | [HighLevel](third_party/highlevel/) | Cursor | Integrations | Work with contacts, conversations, opportunities, calendars, and payments. | diff --git a/plugins-main/pstack/README.md b/plugins-main/pstack/README.md index dbbef9b..4e8b8c2 100644 --- a/plugins-main/pstack/README.md +++ b/plugins-main/pstack/README.md @@ -215,7 +215,7 @@ twenty-four short skills, one principle each. `poteto-mode` indexes them inline | [laziness-protocol](./skills/principle-laziness-protocol/SKILL.md) | core | Bias toward deletion and the smallest change that solves the problem. | | [foundational-thinking](./skills/principle-foundational-thinking/SKILL.md) | core | Apply before writing logic: choosing core types and data structures, sequencing scaffold-vs-feature work, asking what concurrent actors share. Get the data structures right so downstream code becomes obvious. | | [redesign-from-first-principles](./skills/principle-redesign-from-first-principles/SKILL.md) | core | Redesign as if the requirement had been a foundational assumption from day one, instead of bolting it on. | -| [attack-the-premise](./skills/principle-attack-the-premise/SKILL.md) | core | Apply when two or more fixes that share one premise have failed the same gate. Take a census of which actors hold the imbalance before the next fix, then question the premise instead of writing another fix that assumes it. | +| [attack-the-premise](./skills/principle-attack-the-premise/SKILL.md) | core | Apply when two or more fixes that share one premise have failed the same gate. Write the premise down and test it directly before you write another fix that assumes it. | | [subtract-before-you-add](./skills/principle-subtract-before-you-add/SKILL.md) | core | Remove dead weight, redundant validators, and stub references first, then build on the simpler base. | | [minimize-reader-load](./skills/principle-minimize-reader-load/SKILL.md) | core | Count layers between question and answer, and hidden state in the reader's head; collapse one-caller wrappers and shrink mutable scope. | | [outcome-oriented-execution](./skills/principle-outcome-oriented-execution/SKILL.md) | core | Apply during planned rewrites and migrations with explicit phase boundaries. Converge on the target architecture; don't preserve smooth intermediate states with throwaway compatibility code. | @@ -224,14 +224,14 @@ twenty-four short skills, one principle each. `poteto-mode` indexes them inline | [build-the-lever](./skills/principle-build-the-lever/SKILL.md) | core | Apply to any non-trivial work, not just bulk work: edits, migrations, analyses, checks. Build the tool that does it or proves it (codemod, script, generator, or a skill your subagents follow) instead of working by hand. The tool is the artifact a reviewer can rerun. | | [model-the-domain](./skills/principle-model-the-domain/SKILL.md) | architecture | Encode the domain in a structure instead of scattered conditionals. | | [boundary-discipline](./skills/principle-boundary-discipline/SKILL.md) | architecture | Concentrate guards at system boundaries (CLI, config, network, external APIs); trust internal types and keep business logic in pure functions. | -| [type-system-discipline](./skills/principle-type-system-discipline/SKILL.md) | architecture | Make illegal states unrepresentable, brand semantic primitives, parse external data at boundaries, refuse to lie to the compiler, exhaust variants, derive from authoritative schemas. | +| [type-system-discipline](./skills/principle-type-system-discipline/SKILL.md) | architecture | Make illegal states unrepresentable, brand semantic primitives, parse external data at boundaries, exhaust variants, derive from authoritative schemas. | | [make-operations-idempotent](./skills/principle-make-operations-idempotent/SKILL.md) | architecture | Converge to the same end state regardless of partial prior runs. | | [migrate-callers-then-delete-legacy-apis](./skills/principle-migrate-callers-then-delete-legacy-apis/SKILL.md) | architecture | Migrate callers and delete the old API in the same wave instead of preserving compatibility layers. | | [separate-before-serializing-shared-state](./skills/principle-separate-before-serializing-shared-state/SKILL.md) | architecture | Eliminate the sharing first; serialize structurally only when one shared writer is a real invariant. | | [prove-it-works](./skills/principle-prove-it-works/SKILL.md) | verification | Apply after completing a task, before declaring done. Verify against the real artifact (run the feature, read the actual value, inspect the diff), not a proxy, self-report, or 'it compiles.'. | -| [fix-root-causes](./skills/principle-fix-root-causes/SKILL.md) | verification | Trace each symptom to its root cause and fix it there; reproduce first, ask why until you reach it, resist nil-check guards that silence crashes. | +| [fix-root-causes](./skills/principle-fix-root-causes/SKILL.md) | verification | Trace each symptom back to the first place the system went wrong and fix it there. A guard is a fix only when the state it handles is legitimate. | | [sequence-verifiable-units](./skills/principle-sequence-verifiable-units/SKILL.md) | verification | Apply to multi-step work (sweeps, migrations, runs of similar edits) and to how you stack commits and PRs. Break work into small units that each end in a verifiable state, check each before the next, and order delivery so the sequence proves itself to a reviewer. | -| [test-behavior-not-implementation](./skills/principle-test-behavior-not-implementation/SKILL.md) | verification | Apply when you write, change, or keep a test. Call the code the way its users do and assert the result they observe against a literal expected value. If the test would still pass when every imported function returns undefined, rewrite the assertion or delete the test. | +| [test-behavior-not-implementation](./skills/principle-test-behavior-not-implementation/SKILL.md) | verification | Apply when you write, change, or keep a test. Assert what the code's users can observe, so the test fails when that behavior breaks and keeps passing when only the internals change. | | [explain-the-number](./skills/principle-explain-the-number/SKILL.md) | verification | Apply before you trust, report, or act on a number you measured: a speedup, a regression, a throughput, a latency, or an eval result. Find what limits it, and rule out that it measured something other than the work you think. | | [guard-the-context-window](./skills/principle-guard-the-context-window/SKILL.md) | delegation | Route bulk to subagents; keep summaries in the main thread, not raw payloads. | | [never-block-on-the-human](./skills/principle-never-block-on-the-human/SKILL.md) | delegation | Proceed, present the result, let the human course-correct after the fact; reserve confirmation for irreversible actions. | diff --git a/plugins-main/pstack/docs/guide/08-principles.md b/plugins-main/pstack/docs/guide/08-principles.md index 0aaec93..5b17980 100644 --- a/plugins-main/pstack/docs/guide/08-principles.md +++ b/plugins-main/pstack/docs/guide/08-principles.md @@ -33,7 +33,7 @@ The core principles decide how much to build and when to rethink the design: - [Laziness Protocol](../../skills/principle-laziness-protocol/SKILL.md) prefers deletion and the smallest change that solves the problem. - [Foundational Thinking](../../skills/principle-foundational-thinking/SKILL.md) chooses the core data structures before writing logic. - [Redesign from First Principles](../../skills/principle-redesign-from-first-principles/SKILL.md) integrates a new requirement as if it had been there from day one. -- [Attack the Premise](../../skills/principle-attack-the-premise/SKILL.md) questions the premise that two or more failed fixes shared, after a census of which actors hold the imbalance. +- [Attack the Premise](../../skills/principle-attack-the-premise/SKILL.md) writes down the premise that two or more failed fixes shared and tests it directly before the next fix. - [Subtract Before You Add](../../skills/principle-subtract-before-you-add/SKILL.md) removes dead weight before building on top of it. - [Minimize Reader Load](../../skills/principle-minimize-reader-load/SKILL.md) collapses layers and hidden state a reader must hold in their head. - [Outcome-Oriented Execution](../../skills/principle-outcome-oriented-execution/SKILL.md) converges rewrites on the target design instead of preserving throwaway compatibility states. @@ -55,7 +55,7 @@ The verification principles define what counts as proof: - [Prove It Works](../../skills/principle-prove-it-works/SKILL.md) verifies the real artifact, not a proxy. - [Fix Root Causes](../../skills/principle-fix-root-causes/SKILL.md) reproduces and traces to the cause before changing code. - [Sequence Work into Verifiable Units](../../skills/principle-sequence-verifiable-units/SKILL.md) ends each small unit in a check before starting the next. -- [Test Behavior, Not Implementation](../../skills/principle-test-behavior-not-implementation/SKILL.md) calls the code the way its users do and asserts a literal expected value, and deletes a test that would still pass if every imported function returned `undefined`. +- [Test Behavior, Not Implementation](../../skills/principle-test-behavior-not-implementation/SKILL.md) asserts what the code's users can observe, so a test fails when that behavior breaks and survives a change to the internals. - [Explain the Number](../../skills/principle-explain-the-number/SKILL.md) names what limits a measured number and rules out that it measured something else, before anyone trusts or reports it. [`/benchmark-checklist`](../../skills/benchmark-checklist/SKILL.md) turns it into seven questions you answer from real runs. The delegation principles keep parallel work sane: diff --git a/plugins-main/pstack/skills/correct/SKILL.md b/plugins-main/pstack/skills/correct/SKILL.md index c09f486..c45e06f 100644 --- a/plugins-main/pstack/skills/correct/SKILL.md +++ b/plugins-main/pstack/skills/correct/SKILL.md @@ -18,7 +18,7 @@ First, read recent commits, reverts, review comments, agent instruction files, a 1. **Eliminate it with architecture.** Give each piece of state one owner and each task one supported way. Hide internals so the wrong import fails. Replace hand-synced lists with one source of truth. Delete old ways and dead code an agent would copy. 2. **Enforce it with types so the bad state can't be written.** If bad code still compiles, add a lint or CI check whose error names the file, type, or function to use instead. If the pattern is already common, fail only when a change adds more. -3. **Test the behavior.** Fix or delete any test that would still pass if every function it calls returned nothing. +3. **Test the behavior.** Fix or delete any test that still passes when the behavior it checks breaks, or that fails when only the internals change. 4. **Write docs or agent rules last, only for judgment calls.** Nothing fails when an agent skips them. ## Fix and prove diff --git a/plugins-main/pstack/skills/interrogate/references/lead-judgment.md b/plugins-main/pstack/skills/interrogate/references/lead-judgment.md index 5ce5260..3b41346 100644 --- a/plugins-main/pstack/skills/interrogate/references/lead-judgment.md +++ b/plugins-main/pstack/skills/interrogate/references/lead-judgment.md @@ -1,18 +1,5 @@ # Lead Judgment Framework -You are the lead reviewer. The configured reviewers have produced their findings. Apply pragmatic engineering judgment. Don't aggregate. Filter, contextualize, and decide. - -## Why This Step Matters - -Adversarial reviewers are useful because they're aggressive. But aggression without context produces noise. The reviewers only saw a slice of the codebase and a one-paragraph intent statement. They don't know: - -- What was already tried and rejected -- What constraints exist outside the code (timeline, dependencies, migration plans) -- Which parts of the code are temporary scaffolding vs. permanent architecture -- What the next PR in the stack will address - -You have the full conversation context. Use it. - ## Filtering Principles ### Nitpick Gravity @@ -50,9 +37,3 @@ Don't dismiss findings just because they're uncomfortable. The whole point of ad - You read the finding and think "...yeah, actually" Be especially careful about dismissing security findings and correctness bugs. These deserve more scrutiny even when they come from a single model. - -## Verdict Calibration - -A good verdict is useful, not comprehensive. The user should be able to read the "Act On" section, fix those issues, and ship with confidence. If your "Act On" list has more than 5 items, you're probably not filtering hard enough. - -The "Dismissed" section is not busywork. It's a trust mechanism. Showing the user what you rejected and why lets them override your judgment where they disagree. This is more valuable than hiding the rejected findings. diff --git a/plugins-main/pstack/skills/poteto-mode/SKILL.md b/plugins-main/pstack/skills/poteto-mode/SKILL.md index ac3d64f..9295b7e 100644 --- a/plugins-main/pstack/skills/poteto-mode/SKILL.md +++ b/plugins-main/pstack/skills/poteto-mode/SKILL.md @@ -44,7 +44,7 @@ Read the leaf skill in full for any principle you apply. Each entry names when i - **Laziness Protocol.** Refactoring, sizing a diff, or tempted to add abstractions, layers, or signal threading. Bias to deletion and the smallest change that solves the problem. - **Foundational Thinking.** Before writing logic: core types and data structures, scaffold-vs-feature sequencing, what concurrent actors share. - **Redesign from First Principles.** Integrating a new requirement into an existing design. Redesign as if it had been foundational from day one. -- **Attack the Premise.** Two or more fixes that share one premise have failed the same gate. Take a census of which actors hold the imbalance before the next fix, then question the premise instead of writing another fix that assumes it. +- **Attack the Premise.** Two or more fixes that share one premise have failed the same gate. Write the premise down and test it directly before you write another fix that assumes it. - **Subtract Before You Add.** Sequencing an addition, refactor, or rewrite. Remove dead weight first, then build on the simpler base. - **Minimize Reader Load.** Reviewing or shaping code that's hard to trace. Count layers and hidden state, collapse one-caller wrappers, shrink mutable scope. - **Outcome-Oriented Execution.** Planned rewrites and migrations with explicit phase boundaries. Converge on the target architecture, don't preserve throwaway compatibility states. @@ -64,9 +64,9 @@ Read the leaf skill in full for any principle you apply. Each entry names when i **Verification** - **Prove It Works.** After a task, before declaring done. Verify against the real artifact, not a proxy or "it compiles". -- **Fix Root Causes.** Debugging. Trace each symptom to its root cause, reproduce first, ask why until you reach it. +- **Fix Root Causes.** Debugging. Trace each symptom back to the first place the system went wrong and fix it there. A guard is a fix only when the state it handles is legitimate. - **Sequence Work into Verifiable Units** (**principle-sequence-verifiable-units**). Multi-step work (sweeps, migrations, runs of similar edits) and how you stack commits and PRs. Break work into small units that each end in a check, verify each before the next, and order delivery so the sequence proves itself. -- **Test Behavior, Not Implementation.** Writing, changing, or keeping a test. Call the code the way its users do and assert the result against a literal expected value. If the test would still pass when every imported function returns `undefined`, rewrite the assertion or delete the test. +- **Test Behavior, Not Implementation.** Writing, changing, or keeping a test. Assert what the code's users can observe, so the test fails when that behavior breaks and keeps passing when only the internals change. - **Explain the Number.** Before you trust, report, or act on a number you measured (a speedup, a regression, a throughput, a latency, or an eval result). Find what limits it, and rule out that it measured something other than the work you think. **Delegation** diff --git a/plugins-main/pstack/skills/principle-attack-the-premise/SKILL.md b/plugins-main/pstack/skills/principle-attack-the-premise/SKILL.md index f9785ff..e9a6d49 100644 --- a/plugins-main/pstack/skills/principle-attack-the-premise/SKILL.md +++ b/plugins-main/pstack/skills/principle-attack-the-premise/SKILL.md @@ -1,6 +1,6 @@ --- name: principle-attack-the-premise -description: "Apply when two or more fixes that share one premise have failed the same gate. Take a census of which actors hold the imbalance before the next fix, then question the premise instead of writing another fix that assumes it." +description: "Apply when two or more fixes that share one premise have failed the same gate. Write the premise down and test it directly before you write another fix that assumes it." disable-model-invocation: true --- @@ -8,16 +8,14 @@ disable-model-invocation: true When two or more fixes that share one premise have failed the same gate, suspect the premise, not the fixes. -**Why:** Each failure under a shared premise is evidence about the premise. +**Why:** Each failed fix is evidence against the belief it assumed. A third fix on the same premise spends effort where the evidence already says the cause is not. **Pattern:** - **Write the premise down.** The premise is the one sentence that every failed fix assumed. -- **Take a census before the next fix.** Count the imbalance per actor. The census shows which actors hold the imbalance, not how large it is. Write the census as a rerunnable script per [Build the Lever](../principle-build-the-lever/SKILL.md). -- **Read the skew.** If the same few actors hold most of the imbalance on every run, something assigns them that role. Find what assigns the role. That assignment is the next "why" per [Fix Root Causes](../principle-fix-root-causes/SKILL.md). -- **Remove the asymmetry instead of compensating for it**, per the [Laziness Protocol](../principle-laziness-protocol/SKILL.md). Rotate the role between actors, randomize the assignment, or move the role, so that no actor holds it on every run. A return path, a shared pool, a batched hand-off, or a periodic rebalance leaves the assignment in place and adds work on every run. +- **Test the premise before the next fix.** Find an observation that would come out differently if the premise were false, and make it. Look at how the failures are distributed, not only at how large they are. Make the check rerunnable per [Build the Lever](../principle-build-the-lever/SKILL.md). +- **Follow the evidence.** If it contradicts the premise, the cause is elsewhere. Look for what the failures have in common that the premise did not predict. If it confirms the premise, ask the next "why" per [Fix Root Causes](../principle-fix-root-causes/SKILL.md). The earlier fixes may have treated a consequence instead of the cause. +- **Remove the condition instead of compensating for it**, per the [Laziness Protocol](../principle-laziness-protocol/SKILL.md). If the evidence shows that one part always lands on the losing side, change what puts it there. A mechanism that cleans up after it leaves the cause in place and adds work on every run. -**Stop:** -- Do not start the next fix before the premise is written down and the census exists. -- If the census is even across actors, the premise is not the cause. Look for the cause elsewhere and keep the census as evidence. +**Stop:** Do not start the next fix before the premise is written down and tested. This principle is distinct from [Redesign from First Principles](../principle-redesign-from-first-principles/SKILL.md), which rebuilds a design around a new requirement. It questions a fact the current design assumes. diff --git a/plugins-main/pstack/skills/principle-fix-root-causes/SKILL.md b/plugins-main/pstack/skills/principle-fix-root-causes/SKILL.md index 5291682..14fc189 100644 --- a/plugins-main/pstack/skills/principle-fix-root-causes/SKILL.md +++ b/plugins-main/pstack/skills/principle-fix-root-causes/SKILL.md @@ -1,24 +1,21 @@ --- name: principle-fix-root-causes -description: "Apply when debugging. Trace each symptom to its root cause and fix it there; reproduce first, ask why until you reach it, resist nil-check guards that silence crashes." +description: "Apply when debugging. Trace each symptom back to the first place the system went wrong and fix it there. A guard is a fix only when the state it handles is legitimate." disable-model-invocation: true --- # Fix Root Causes -When debugging, do not fix symptoms. Trace every problem to its root cause and fix it there. +When debugging, fix the fault, not the place where it surfaced. The symptom is where a wrong state became visible. The root cause is the first place the system did something it should not do, or failed to handle a state it should handle. -**Why:** Symptom fixes accumulate. Each workaround makes the system harder to reason about, and the real bug remains. Root-cause fixes are slower upfront but reduce total debugging time. +**Why:** A symptom fix hides the evidence and leaves the fault free to surface somewhere else. Each one makes the system harder to reason about, because the code now carries a workaround for a bug that nobody named. **Pattern:** -- Reproduce first -- Ask "why" until you hit the root cause -- Do not add guards (adding a nil check to silence a crash is a symptom fix) -- If a workaround needs a paragraph-long comment to justify it, the code is wrong (fix the code, not the comment) -- Check for the pattern, not just the instance (grep for the same pattern, fix all instances) -- When stuck, instrument. Don't guess (add logging, read the actual error) -- If the deciding fact took a deep dig to find, propose the cheap, always-on signal that would have shown it at first look - -**Restart bugs: suspect state before code** - -When something "fails after restart," suspect stale persistent state first: config files, caches, lock files, serialized state. If clearing a state file restores behavior, prioritize state validation as the fix. +- Reproduce first. +- Ask "why" at each step until the answer is a wrong decision in the code, not a consequence of an earlier one. +- When stuck, instrument. Read the actual error and the actual state. Do not guess. +- Ask whether the state that triggered the symptom is legitimate. If the system may be in that state, the code that broke on it is the root cause, and handling the state there is the fix. If the state should never exist, a check where it broke hides the bug. Find what produced the state. Guards, retries, swallowed errors, clamped values, and discarded state are the usual ways to hide a bug. +- When something fails only after a restart, suspect persisted state first: config files, caches, lock files, serialized state. +- Check for the pattern, not just the instance. Find every place with the same fault and fix them all. +- If a workaround needs a paragraph-long comment to justify it, the code is wrong. Fix the code, not the comment. +- If the deciding fact took a deep dig to find, propose the cheap, always-on signal that would have shown it at first look. diff --git a/plugins-main/pstack/skills/principle-make-operations-idempotent/SKILL.md b/plugins-main/pstack/skills/principle-make-operations-idempotent/SKILL.md index a083424..c93f323 100644 --- a/plugins-main/pstack/skills/principle-make-operations-idempotent/SKILL.md +++ b/plugins-main/pstack/skills/principle-make-operations-idempotent/SKILL.md @@ -6,15 +6,13 @@ disable-model-invocation: true # Make Operations Idempotent -Design operations so they converge to the correct state regardless of how many times they run or where they start from. Every state-mutating operation should answer: "What happens if this runs twice? What happens if the previous run crashed halfway?" +Design operations so they converge to the correct state regardless of how many times they run or where the previous run stopped. Every state-mutating operation should answer: "What happens if this runs twice? What happens if the previous run crashed halfway?" **Why:** Commands, lifecycle operations, and processing loops run where crashes, restarts, and retries are normal. If partial state changes the next run's outcome, every restart becomes a debugging session. -**The pattern:** -- Convergent startup: scan for existing state, clean stale artifacts, adopt live sessions -- Content-based cleanup: compare by content equivalence, not creation order -- Self-healing locks: use PID-based stale lock detection -- Idempotent scheduling: failed work respawns cleanly, fresh input regenerated after each cycle +**The idea:** derive each step from the state that exists, not from what the previous run meant to do. Read the current state, compare it to the goal, and apply only the difference. A step written this way is safe to repeat, because a repeat finds nothing left to do. + +Anything a run leaves behind, such as a lock, a temporary file, a half-written record, or a claimed job, must be recognizable as stale by the next run. Judge staleness by evidence that stays true wherever the previous run could have stopped, not only in the common case. A marker that the next run cannot judge turns every crash into manual cleanup. For example, write to a temporary path and rename it into place, or compare artifacts by content instead of by creation order. **The test:** 1. What happens if this runs twice in a row? diff --git a/plugins-main/pstack/skills/principle-migrate-callers-then-delete-legacy-apis/SKILL.md b/plugins-main/pstack/skills/principle-migrate-callers-then-delete-legacy-apis/SKILL.md index 06c7cfd..57ddd7b 100644 --- a/plugins-main/pstack/skills/principle-migrate-callers-then-delete-legacy-apis/SKILL.md +++ b/plugins-main/pstack/skills/principle-migrate-callers-then-delete-legacy-apis/SKILL.md @@ -6,17 +6,9 @@ disable-model-invocation: true # Migrate Callers Then Delete Legacy APIs -When we decide a new API is the right design, migrate callers and remove the old API in the same refactor wave instead of preserving compatibility layers. - -**Rule:** -- Do not keep legacy API paths only because internal callers still exist -- Inventory callers, migrate them, and delete the old API immediately -- Treat temporary adapters as exceptional and time-boxed, not default architecture - Update tests to assert the new contract, and delete tests that only protect pre-refactor implementation details **When this applies:** - No external users depend on backward compatibility - The project can absorb coordinated breaking changes - The new API is part of a simplification or refactor initiative - -Keeping both old and new APIs creates dual-path complexity, slows cleanup, and makes the codebase feel append-only. diff --git a/plugins-main/pstack/skills/principle-test-behavior-not-implementation/SKILL.md b/plugins-main/pstack/skills/principle-test-behavior-not-implementation/SKILL.md index f5a603e..78c9389 100644 --- a/plugins-main/pstack/skills/principle-test-behavior-not-implementation/SKILL.md +++ b/plugins-main/pstack/skills/principle-test-behavior-not-implementation/SKILL.md @@ -1,21 +1,20 @@ --- name: principle-test-behavior-not-implementation -description: "Apply when you write, change, or keep a test. Call the code as its users do and assert the exact result they see. Rewrite or delete a test that would pass if every imported function returned undefined." +description: "Apply when you write, change, or keep a test. Assert what the code's users can observe, so that the test fails when that behavior breaks and keeps passing when only the internals change." disable-model-invocation: true --- # Test Behavior, Not Implementation -A test calls the code as its users do and asserts the exact result they see. Rewrite or delete any test that would still pass if every imported function returned `undefined` or a wrong value. +A test is a claim about what the code does for its users: a caller, an end user, or another service. Behavior is what those users can observe through the interface they use. That includes return values, errors, state they can read back, and effects on systems outside the code, such as a request sent, a row written, or a message emitted. Implementation is what they cannot observe: private helpers, internal call order, intermediate data, and which internal collaborator did the work. -These shapes fail that check: +Judge each test against two imagined edits: -- Loose or no assertion: `toBeDefined`, `toBeTruthy`, `not.toThrow`, `toBeGreaterThan(0)`. -- Call or absence only: `toHaveBeenCalled`, `not.toHaveBeenCalled`, `toBeUndefined`, `toEqual([])`. -- Expected value computed by the code under test: `expect(f(a)).toBe(f(a))`. -- Restated constant, config default, table row, or prompt string. -- Assertions on data the test built, with no call to the subject. +- **Break the behavior.** Make the code return a wrong value, skip an effect, or do the effect twice. If the test still passes, it proves nothing. The usual causes are an assertion looser than the contract, an expected value computed by the code under test, a restated constant or prompt string that never runs the code that reads it, and an assertion on data that the test built itself. +- **Change the internals.** Keep every observable result the same and restructure the code underneath. If the test now fails, it is pinned to the implementation. It will need a rewrite on every refactor and still catches no bug. -Fix: call the subject in the test body with one concrete input and assert the literal output or effect. For a mock, assert the payload it received. For an absence, also assert the presence on another input. For a constant, test the mechanism that reads it with one input instead of restating the value. +Keep a test that catches the first edit and survives the second. Rewrite or delete the rest. To write a test that does both, drive the code through its users' interface with a concrete input. Derive the expected value from the requirement, not from a run of the code. Assert what the contract promises, no less and no more. -Keep relation checks across table rows (a key in two tables, a parent that exists) and `*.test-d.ts` type checks. +The contract decides, not the shape of the assertion. When "an empty cart never charges" is the promise, an assertion that the payment client got no call is behavior. Pair it with a case where the charge happens, so that the test shows it can see a call. The payload that a mocked external service receives is behavior, because that service observes it. A call to an internal helper is implementation, because no user can see it. An empty list is the exact answer when no record matches, and a hollow check when the test only needs some result. An exact error message pins wording that no caller reads. The error type that callers branch on is the contract. + +A test can pin an invariant instead of a call, such as a key that must exist in two tables or a compile-time type check. The invariant is the behavior. diff --git a/plugins-main/pstack/skills/principle-type-system-discipline/SKILL.md b/plugins-main/pstack/skills/principle-type-system-discipline/SKILL.md index 4321b83..9fa08b0 100644 --- a/plugins-main/pstack/skills/principle-type-system-discipline/SKILL.md +++ b/plugins-main/pstack/skills/principle-type-system-discipline/SKILL.md @@ -1,6 +1,6 @@ --- name: principle-type-system-discipline -description: "Apply when designing types, reviewing a function signature, or writing code in any statically-typed language. Make illegal states unrepresentable, brand semantic primitives, parse external data at boundaries, refuse to lie to the compiler, exhaust variants, derive from authoritative schemas." +description: "Apply when designing types, reviewing a function signature, or writing code in any statically-typed language. Make illegal states unrepresentable, brand semantic primitives, parse external data at boundaries, exhaust variants, derive from authoritative schemas." disable-model-invocation: true --- @@ -8,11 +8,6 @@ disable-model-invocation: true Make the compiler reject impossible states, mismatched primitives, and unhandled variants. Prefer defining errors and special cases out of existence over proliferating handlers. For TypeScript syntax, see the `typescript-best-practices` skill. -- **Make illegal states unrepresentable.** Model variants as sum types (discriminated unions, enums with payloads, sealed classes), not as a bag of optional fields where contradictory combinations compile. `{ completed: boolean; completedAt?: Date }` admits `completed: true` with no date. Derive the boolean from `completedAt`, or model `{ kind: 'open' } | { kind: 'done'; at: Date }`. If you can write a comment explaining when a combination of fields is valid, split it into a sum type. -- **Types are constructions, not restrictions.** Build the type up from the values you want instead of carving them out of a looser type with checks. A non-empty list is a head plus a rest. A valid time range is a start plus a duration. Choose the shape that cannot build the illegal value and expose the interface callers need on top. - **Brand semantic primitives.** `UserId` and `OrderId` are strings underneath but should not be interchangeable. Give each its own type, such as a branded intersection in TypeScript or a newtype elsewhere. Validate once at creation, trust the type downstream. If two arguments share a primitive type but mean different things, brand them. - **External data is untyped until parsed.** RPC payloads, JSON, IPC messages, CLI args, config files, environment variables, database rows. Have a parse function at every boundary that turns unstructured input into the typed model. The **boundary-discipline** principle skill says where to put validation. -- **Don't lie to the type system.** Casts, unsafe coercions, and assertion functions that bypass the compiler are latent runtime crashes. If the compiler can't prove a fact, prove it (validate, narrow, refine the model) or accept that the cast is a hazard. Trace each `any`, `as`, or `assertNotNull` to the boundary and validate there. -- **Exhaustive matching is the compiler's job.** A match on a sum type must fail compilation when a new variant is added without handling, so the compiler tells the next agent where to add a case. Use your language's idiom: a `never`-typed binding in TypeScript, an unannotated `match` in Rust, `-Wincomplete-patterns` in Haskell, sealed-class match exhaustiveness in Kotlin. - **Derive types from authoritative schemas.** When a protocol buffer, OpenAPI spec, GraphQL schema, database migration, design-token file, or another file owns a shape, derive from it instead of hand-rolling a parallel type. See the **encode-lessons-in-structure** principle skill. -- **Strengthen a type only where partiality appears.** A runtime assertion, null check, or "this should never happen" throw marks the place a type is too weak. Push that check up into the type. Then stop. The type system's job is to track the cases each use site must handle, not to describe the data as precisely as possible. Prefer total functions. `sum` of an empty list is 0, so it takes the plain list. `head` of an empty list has no answer, so it demands the non-empty one. If nothing would otherwise panic, keep the plain type. diff --git a/plugins-main/pstack/skills/swarm/SKILL.md b/plugins-main/pstack/skills/swarm/SKILL.md index ed99acb..b0b1eb8 100644 --- a/plugins-main/pstack/skills/swarm/SKILL.md +++ b/plugins-main/pstack/skills/swarm/SKILL.md @@ -6,8 +6,6 @@ disable-model-invocation: true # Swarm -Fan out N parallel cloud workers. They may cover separate slices, race the same brief, or mix both. The parent waits, aggregates, and returns one report. - ## Start Open a todolist with one entry per phase before launching anything. @@ -21,7 +19,6 @@ Open a todolist with one entry per phase before launching anything. 1. State the done predicate and the artifact or report the swarm must return. 2. Choose the shape. Partition into slices, race N workers on identical briefs, or mix both. For a race or mixed shape, declare `first pass`, `rank all`, or `best-of` before spawning. -3. Set N from the user or derive it from the shape. N is total workers, not the cloud concurrency limit. 4. Pick the worker model from the `swarm workers` line in `~/.cursor/rules/pstack-models.mdc`. If the rule or that line is missing, use `grok-4.7-xhigh-fast`. For `auto` or `inherit-parent`, omit `model` so the workers run on the parent model. If the Task tool rejects a slug, use the default and say so. If it rejects the default, use the closest valid slug of the same family from its error message. For a model race, name each arm's model up front. Pick each subagent's reasoning level and fast or standard speed for the job, per the Subagents section of the **poteto-mode** skill. 5. Give each worker its own writable output when it writes. When workers verify or measure commits, each brief names the exact SHAs. A measurement brief also names the method (sample count, what one sample is, order). The worker records both in its result. @@ -39,8 +36,6 @@ If a worker drops out, proceed with N-1 and note it. Read the terminal results. Drop a result that does not record the SHAs and method its brief names, and respawn that worker once. After a second miss, record a gap. A gap does not count as a pass. For coverage, every required slice needs a result. For a race, apply the selection rule declared up front. Use first pass, rank all, or best-of. Do not paste raw worker dumps. -Keep a compact result table, one-line evidenced issues, and explicit gaps or dropouts. - ## Phase D: Report Return one consolidated in-chat report with the table, issue one-liners, gaps or dropouts, and the race rule when used. diff --git a/plugins-main/third_party/whatsapp-business/.cursor-plugin/plugin.json b/plugins-main/third_party/whatsapp-business/.cursor-plugin/plugin.json new file mode 100644 index 0000000..373917f --- /dev/null +++ b/plugins-main/third_party/whatsapp-business/.cursor-plugin/plugin.json @@ -0,0 +1,63 @@ +{ + "name": "whatsapp-business", + "displayName": "WhatsApp Business", + "version": "1.0.0", + "minClientVersions": { + "cursor": "3.19.0" + }, + "description": "Send messages and manage templates, contacts, and phone numbers in WhatsApp Business.", + "author": { + "name": "Cursor", + "email": "plugins@cursor.com" + }, + "homepage": "https://github.com/cursor/plugins/tree/main/third_party/whatsapp-business", + "repository": "https://github.com/cursor/plugins", + "license": "MIT", + "logo": "assets/logo.png", + "keywords": [ + "whatsapp", + "whatsapp business", + "meta", + "messaging", + "mcp" + ], + "category": "integrations", + "tags": [ + "whatsapp", + "whatsapp business", + "meta", + "messaging", + "mcp" + ], + "variables": { + "type": "object", + "additionalProperties": false, + "required": [ + "WHATSAPP_BUSINESS_ACCOUNT_ID", + "WHATSAPP_BUSINESS_PHONE_NUMBER_ID", + "WHATSAPP_BUSINESS_ACCESS_TOKEN" + ], + "properties": { + "WHATSAPP_BUSINESS_ACCOUNT_ID": { + "type": "string", + "title": "WhatsApp Business Account ID", + "description": "Shown next to your account name in WhatsApp Manager.", + "minLength": 1 + }, + "WHATSAPP_BUSINESS_PHONE_NUMBER_ID": { + "type": "string", + "title": "Phone number ID", + "description": "The long numeric ID under Account tools > Phone numbers in WhatsApp Manager, not the phone number itself.", + "minLength": 1 + }, + "WHATSAPP_BUSINESS_ACCESS_TOKEN": { + "type": "string", + "title": "Access token", + "description": "A system user token with the whatsapp_business_messaging and whatsapp_business_management permissions.", + "writeOnly": true, + "format": "password", + "minLength": 1 + } + } + } +} diff --git a/plugins-main/third_party/whatsapp-business/CHANGELOG.md b/plugins-main/third_party/whatsapp-business/CHANGELOG.md new file mode 100644 index 0000000..eb7206e --- /dev/null +++ b/plugins-main/third_party/whatsapp-business/CHANGELOG.md @@ -0,0 +1,11 @@ +# Changelog + +All notable changes to this plugin will be documented here. + +## 1.0.0 — initial release + +- Added the `whatsapp-business` plugin, the opt-in for the WhatsApp Business MCP server that Cursor hosts. +- Carries no MCP server definition: the server is Cursor-side, so installing the plugin is the whole configuration. +- Each member enters their own `WHATSAPP_BUSINESS_ACCOUNT_ID`, `WHATSAPP_BUSINESS_PHONE_NUMBER_ID`, and `WHATSAPP_BUSINESS_ACCESS_TOKEN`. These are per-member values, not team settings. +- The access token is a Meta system user token with the `whatsapp_business_messaging` and `whatsapp_business_management` permissions. +- Logo: WhatsApp's official mark, from `whatsapp.com`. diff --git a/plugins-main/third_party/whatsapp-business/LICENSE b/plugins-main/third_party/whatsapp-business/LICENSE new file mode 100644 index 0000000..ca2bba7 --- /dev/null +++ b/plugins-main/third_party/whatsapp-business/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Cursor + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/plugins-main/third_party/whatsapp-business/README.md b/plugins-main/third_party/whatsapp-business/README.md new file mode 100644 index 0000000..b4e4e9e --- /dev/null +++ b/plugins-main/third_party/whatsapp-business/README.md @@ -0,0 +1,77 @@ +# WhatsApp Business + +Cursor plugin that connects agents to [WhatsApp Business](https://business.whatsapp.com) — Meta's messaging platform for businesses — through a [Model Context Protocol](https://modelcontextprotocol.io/) server that Cursor hosts. + +Work with a WhatsApp Business Account: send messages from your business phone number, manage message templates, and look up contacts and phone numbers. + +## Install + +1. Open **Cursor Settings → Plugins**. +2. Search for **WhatsApp Business** and click **Install**. +3. Enter your WhatsApp Business Account ID, phone number ID, and access token (see [Before you connect](#before-you-connect)). + +Or run `/add-plugin whatsapp-business` in chat. + +## MCP + +This plugin ships no `mcp.json`, and that is deliberate. + +Every other connector in this repository either points at a vendor's hosted endpoint or runs a package locally over stdio, so it carries its own server definition. WhatsApp Business does not: Cursor runs the server, and the plugin exists only as the opt-in that turns it on for your account. There is no command to run and no MCP endpoint to configure. + +One consequence worth knowing: because the server is not declared here, you will not find it in a local `mcp.json` and you cannot point another MCP client at it. It is reachable from Cursor only. + +## Before you connect + +Each person who installs the plugin enters their own three values. These are per-member settings, so a team admin cannot set them for everyone. + +### 1. Create a system user token in Meta + +1. In [Meta Business Suite](https://business.facebook.com), open **Business settings → Users → System users** and add a system user, or pick an existing one. +2. Under **Assign assets**, give the system user access to your WhatsApp Business Account. +3. Click **Generate new token**, choose the Meta app connected to your WhatsApp Business Account, and select the `whatsapp_business_messaging` and `whatsapp_business_management` permissions. +4. Copy the token. Meta shows it only once. + +### 2. Find your IDs in WhatsApp Manager + +- **WhatsApp Business Account ID:** shown next to your account name in [WhatsApp Manager](https://business.facebook.com/wa/manage/home/). +- **Phone number ID:** the long numeric ID under **Account tools → Phone numbers**. Use the ID, not the phone number itself. + +### 3. Enter the values in Cursor + +All three fields are required: + +| Field | Value | +| --- | --- | +| `WHATSAPP_BUSINESS_ACCOUNT_ID` | WhatsApp Business Account ID from WhatsApp Manager. | +| `WHATSAPP_BUSINESS_PHONE_NUMBER_ID` | Phone number ID from **Account tools → Phone numbers**. Agents send messages from this number. | +| `WHATSAPP_BUSINESS_ACCESS_TOKEN` | The system user token from step 1. Treated as a secret and never shown back. | + +## What agents can do + +| Category | Capabilities | +| --- | --- | +| Messages | Send text and template messages from your business phone number | +| Templates | List and manage message templates | +| Contacts | Look up the contacts your business messages | +| Phone numbers | Read the phone numbers on your WhatsApp Business Account | + +The server is the source of truth for tool names and schemas. + +## Notes + +- Access follows the system user token. The connector can reach only the WhatsApp Business Accounts assigned to that system user, within the token's permissions. +- WhatsApp only allows free-form messages within 24 hours of a customer's last message. Outside that window, agents must send an approved template. +- Messages go out from your real business number and can incur Meta's messaging charges. Review what agents send. +- Disconnecting the connector in Cursor deletes your saved account ID, phone number ID, and access token. Revoking the token in Meta Business Settings ends Cursor's access to your account. + +## Docs + +- WhatsApp Business Platform: https://business.whatsapp.com +- WhatsApp Cloud API: https://developers.facebook.com/docs/whatsapp/cloud-api +- Model Context Protocol: https://modelcontextprotocol.io + +Logo is WhatsApp's official mark, from `whatsapp.com`. + +## License + +MIT diff --git a/plugins-main/third_party/whatsapp-business/assets/logo.png b/plugins-main/third_party/whatsapp-business/assets/logo.png new file mode 100644 index 0000000..aca3c0e Binary files /dev/null and b/plugins-main/third_party/whatsapp-business/assets/logo.png differ