@codyswann/lisa 2.176.12 → 2.177.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/rules/eager/integration-access-layer.md +10 -0
- package/plugins/lisa/rules/reference/integration-access-layer.md +56 -0
- package/plugins/lisa/skills/jam-access/SKILL.md +51 -0
- package/plugins/lisa/skills/jam-access/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/linear-access/SKILL.md +90 -0
- package/plugins/lisa/skills/linear-access/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/posthog-access/SKILL.md +60 -0
- package/plugins/lisa/skills/posthog-access/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/sentry-access/SKILL.md +56 -0
- package/plugins/lisa/skills/sentry-access/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/sonarcloud-access/SKILL.md +71 -0
- package/plugins/lisa/skills/sonarcloud-access/agents/openai.yaml +4 -0
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/skills/jam-access/SKILL.md +51 -0
- package/plugins/lisa-agy/skills/linear-access/SKILL.md +90 -0
- package/plugins/lisa-agy/skills/posthog-access/SKILL.md +60 -0
- package/plugins/lisa-agy/skills/sentry-access/SKILL.md +56 -0
- package/plugins/lisa-agy/skills/sonarcloud-access/SKILL.md +71 -0
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/rules/eager/integration-access-layer.md +10 -0
- package/plugins/lisa-copilot/rules/reference/integration-access-layer.md +56 -0
- package/plugins/lisa-copilot/skills/jam-access/SKILL.md +51 -0
- package/plugins/lisa-copilot/skills/linear-access/SKILL.md +90 -0
- package/plugins/lisa-copilot/skills/posthog-access/SKILL.md +60 -0
- package/plugins/lisa-copilot/skills/sentry-access/SKILL.md +56 -0
- package/plugins/lisa-copilot/skills/sonarcloud-access/SKILL.md +71 -0
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/rules/integration-access-layer-reference.mdc +61 -0
- package/plugins/lisa-cursor/rules/integration-access-layer.mdc +15 -0
- package/plugins/lisa-cursor/skills/jam-access/SKILL.md +51 -0
- package/plugins/lisa-cursor/skills/linear-access/SKILL.md +90 -0
- package/plugins/lisa-cursor/skills/posthog-access/SKILL.md +60 -0
- package/plugins/lisa-cursor/skills/sentry-access/SKILL.md +56 -0
- package/plugins/lisa-cursor/skills/sonarcloud-access/SKILL.md +71 -0
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/src/base/rules/eager/integration-access-layer.md +10 -0
- package/plugins/src/base/rules/reference/integration-access-layer.md +56 -0
- package/plugins/src/base/skills/jam-access/SKILL.md +51 -0
- package/plugins/src/base/skills/linear-access/SKILL.md +90 -0
- package/plugins/src/base/skills/posthog-access/SKILL.md +60 -0
- package/plugins/src/base/skills/sentry-access/SKILL.md +56 -0
- package/plugins/src/base/skills/sonarcloud-access/SKILL.md +71 -0
- package/scripts/generate-codex-plugin-artifacts.mjs +28 -7
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Integration Access Layer
|
|
2
|
+
|
|
3
|
+
Skills and rules that use external integrations route through the matching
|
|
4
|
+
`*-access` skill. Do not call vendor MCP tools or REST APIs directly from a
|
|
5
|
+
consumer skill.
|
|
6
|
+
|
|
7
|
+
Resolution order is MCP when available and authenticated, then documented
|
|
8
|
+
token/REST substrate when the env var is set, then a loud error naming the env
|
|
9
|
+
var. Full matrix and migration rules:
|
|
10
|
+
[reference/integration-access-layer.md](../reference/integration-access-layer.md).
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Integration Access Layer
|
|
2
|
+
|
|
3
|
+
Every Lisa skill or rule that consumes an external integration MUST route through
|
|
4
|
+
the integration's `*-access` skill instead of calling that vendor's MCP tools or
|
|
5
|
+
REST API directly.
|
|
6
|
+
|
|
7
|
+
The access skill owns substrate resolution:
|
|
8
|
+
|
|
9
|
+
1. MCP, when the tool is available and already authenticated to the configured
|
|
10
|
+
workspace/account.
|
|
11
|
+
2. Token/REST substrate, only when the documented env var is present.
|
|
12
|
+
3. Loud failure naming the exact env var to set.
|
|
13
|
+
|
|
14
|
+
Do not blind-retry a failed or absent MCP. Fall back only after checking the
|
|
15
|
+
documented env var for that vendor, and never silently no-op when neither tier is
|
|
16
|
+
available.
|
|
17
|
+
|
|
18
|
+
## Access Skills
|
|
19
|
+
|
|
20
|
+
| Vendor | Access skill | Headless env var | REST/token substrate |
|
|
21
|
+
|---|---|---|---|
|
|
22
|
+
| Atlassian | `lisa:atlassian-access` | `ATLASSIAN_API_TOKEN` | Atlassian Cloud REST |
|
|
23
|
+
| Notion | `lisa:notion-access` | `NOTION_API_TOKEN` | Notion REST |
|
|
24
|
+
| Linear | `lisa:linear-access` | `LINEAR_API_KEY` | Linear GraphQL |
|
|
25
|
+
| Jam | `lisa:jam-access` | `JAM_PAT` | Jam MCP HTTP endpoint with bearer PAT |
|
|
26
|
+
| SonarCloud | `lisa:sonarcloud-access` | `SONAR_TOKEN` | SonarCloud Web API |
|
|
27
|
+
| Sentry | `lisa:sentry-access` | `SENTRY_AUTH_TOKEN` | Sentry REST API |
|
|
28
|
+
| PostHog | `lisa:posthog-access` | `POSTHOG_PERSONAL_API_KEY` | PostHog REST API |
|
|
29
|
+
|
|
30
|
+
## Current Coupling Matrix
|
|
31
|
+
|
|
32
|
+
Source audit date: 2026-06-23. Scope: `plugins/src/**/skills/**` and
|
|
33
|
+
`plugins/src/**/rules/**`.
|
|
34
|
+
|
|
35
|
+
| Vendor | Direct source MCP references | Current route | Retrofit status |
|
|
36
|
+
|---|---:|---|---|
|
|
37
|
+
| Atlassian | setup-only references plus legacy stack-generated sources | `atlassian-access` for base runtime paths | Done for base hot paths; stack overlays still need sync from base patterns when touched. |
|
|
38
|
+
| Notion | setup-only references | `notion-access` | Done. |
|
|
39
|
+
| Linear | Multiple base queue/read/write/verify skills | Raw Linear MCP | Access layer added; consumers still need migration to `linear-access`. |
|
|
40
|
+
| Jam | None in `plugins/src` at audit time | No access layer | Access layer added for host rules that include Jam triage. |
|
|
41
|
+
| SonarCloud | None in `plugins/src` at audit time | No access layer | Access layer added for host rules that include SonarCloud gate triage. |
|
|
42
|
+
| Sentry | No Sentry MCP references in `plugins/src`; CLI/REST mentions only | CLI/REST scattered in observability docs | Access layer added for future MCP-backed consumers. |
|
|
43
|
+
| PostHog | No PostHog MCP references in `plugins/src`; observability docs mention PostHog detection | No access layer | Access layer added for future MCP-backed consumers. |
|
|
44
|
+
|
|
45
|
+
## Migration Rule For Consumers
|
|
46
|
+
|
|
47
|
+
When editing any skill listed in the matrix:
|
|
48
|
+
|
|
49
|
+
- Replace direct `mcp__<vendor>__*` calls in `allowed-tools` with `Skill` and
|
|
50
|
+
delegate to the matching access skill.
|
|
51
|
+
- Keep operation names coarse and vendor-native. Add new operation rows to the
|
|
52
|
+
access skill instead of embedding REST details in the consumer.
|
|
53
|
+
- Preserve existing MCP behavior as the first tier where Claude/Codex can expose
|
|
54
|
+
the MCP, but make headless token fallback explicit and gated by the env var.
|
|
55
|
+
- If a vendor has no documented token substrate, keep the MCP-only behavior and
|
|
56
|
+
fail with a clear "no documented headless substrate" message.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: jam-access
|
|
3
|
+
description: "Vendor-neutral access layer for Jam. Jam triage rules and skills MUST delegate through this skill rather than calling Jam MCP tools directly. Resolves Jam MCP first when available, then falls back to JAM_PAT bearer auth for headless routines."
|
|
4
|
+
allowed-tools: ["Bash", "Read", "Skill"]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Jam Access: $ARGUMENTS
|
|
8
|
+
|
|
9
|
+
Single chokepoint for Jam operations. Caller skills and rules MUST NOT call
|
|
10
|
+
`mcp__Jam__*` tools directly.
|
|
11
|
+
|
|
12
|
+
## Invocation Contract
|
|
13
|
+
|
|
14
|
+
```text
|
|
15
|
+
operation: get-trace url:<jam-url-or-id>
|
|
16
|
+
operation: get-recording url:<jam-url-or-id>
|
|
17
|
+
operation: get-bug-report url:<jam-url-or-id>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Return parsed JSON or a concise structured summary in a `<result>` block.
|
|
21
|
+
|
|
22
|
+
## Substrate Selection
|
|
23
|
+
|
|
24
|
+
Probe in order:
|
|
25
|
+
|
|
26
|
+
1. Jam MCP, if the tool is available and authenticated.
|
|
27
|
+
2. `JAM_PAT` bearer token against Jam's MCP/trace HTTP substrate.
|
|
28
|
+
|
|
29
|
+
Jam documents personal access tokens for MCP clients so a browser OAuth flow is
|
|
30
|
+
not required. The headless tier uses:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
curl -sS "https://mcp.jam.dev/mcp" \
|
|
34
|
+
-H "Authorization: Bearer $JAM_PAT" \
|
|
35
|
+
-H "Content-Type: application/json" \
|
|
36
|
+
--data-binary "$PAYLOAD"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
If neither tier works, fail with:
|
|
40
|
+
|
|
41
|
+
```text
|
|
42
|
+
Error: no Jam access substrate available. Authenticate the Jam MCP or set JAM_PAT.
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Invariants
|
|
46
|
+
|
|
47
|
+
- Fallback is gated on `JAM_PAT`; do not retry Jam MCP failures blindly.
|
|
48
|
+
- Never commit a Jam PAT into `.mcp.json`. Use env interpolation in host MCP
|
|
49
|
+
config, for example `Authorization: Bearer ${JAM_PAT}`.
|
|
50
|
+
- If a requested operation is not yet mapped to the Jam HTTP substrate, surface
|
|
51
|
+
that exact missing adapter instead of pretending the trace is unavailable.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: linear-access
|
|
3
|
+
description: "Vendor-neutral access layer for Linear. Linear skills MUST delegate through this skill rather than calling Linear MCP tools or Linear GraphQL directly. Resolves Linear MCP first when authenticated, then falls back to LINEAR_API_KEY + Linear GraphQL in headless environments."
|
|
4
|
+
allowed-tools: ["Bash", "Read", "Skill"]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Linear Access: $ARGUMENTS
|
|
8
|
+
|
|
9
|
+
Single chokepoint for Linear operations. Caller skills (`linear-*`) MUST go
|
|
10
|
+
through this skill. They MUST NOT call `mcp__linear-server__*` tools directly or
|
|
11
|
+
curl `https://api.linear.app/graphql` themselves.
|
|
12
|
+
|
|
13
|
+
## Invocation Contract
|
|
14
|
+
|
|
15
|
+
```text
|
|
16
|
+
operation: list-teams [query:<KEY>]
|
|
17
|
+
operation: get-team id:<ID>
|
|
18
|
+
operation: list-projects [team:<KEY>] [label:<NAME>] [state:<arr>]
|
|
19
|
+
operation: get-project id:<ID>
|
|
20
|
+
operation: save-project payload:{...}
|
|
21
|
+
operation: list-issues [team:<ID>] [project:<ID>] [label:<NAME>] [state_type:<arr>]
|
|
22
|
+
operation: get-issue id:<ID>
|
|
23
|
+
operation: save-issue payload:{...}
|
|
24
|
+
operation: list-comments issue_id:<ID>
|
|
25
|
+
operation: save-comment issue_id:<ID> body:"..."
|
|
26
|
+
operation: list-issue-labels [team:<ID>]
|
|
27
|
+
operation: create-issue-label payload:{...}
|
|
28
|
+
operation: list-project-labels
|
|
29
|
+
operation: create-project-label payload:{...}
|
|
30
|
+
operation: list-documents project_id:<ID>
|
|
31
|
+
operation: get-document id:<ID>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Return parsed JSON in a `<result>` block. On failure, prefix the message with
|
|
35
|
+
`Error:` and include the failing operation name.
|
|
36
|
+
|
|
37
|
+
## Substrate Selection
|
|
38
|
+
|
|
39
|
+
Read config:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
WORKSPACE=$(jq -r '.linear.workspace // empty' .lisa.config.json 2>/dev/null)
|
|
43
|
+
TEAM_KEY=$(jq -r '.linear.teamKey // empty' .lisa.config.json 2>/dev/null)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Probe in order:
|
|
47
|
+
|
|
48
|
+
1. Linear MCP, if `mcp__linear-server__list_teams` is available and can list the
|
|
49
|
+
configured workspace/team.
|
|
50
|
+
2. `LINEAR_API_KEY` with Linear GraphQL (`https://api.linear.app/graphql`).
|
|
51
|
+
|
|
52
|
+
The Linear GraphQL docs support personal API keys for scripts and authenticate
|
|
53
|
+
with an `Authorization: <API_KEY>` header. Treat `LINEAR_API_KEY` as the
|
|
54
|
+
headless substrate. If neither tier works, fail with:
|
|
55
|
+
|
|
56
|
+
```text
|
|
57
|
+
Error: no Linear access substrate available. Authenticate the Linear MCP or set LINEAR_API_KEY.
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## GraphQL Adapter
|
|
61
|
+
|
|
62
|
+
All GraphQL calls use:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
linear_graphql() {
|
|
66
|
+
local query="$1"
|
|
67
|
+
local variables="${2:-{}}"
|
|
68
|
+
[ -n "$LINEAR_API_KEY" ] || {
|
|
69
|
+
echo "Error: LINEAR_API_KEY is not set." >&2
|
|
70
|
+
return 1
|
|
71
|
+
}
|
|
72
|
+
jq -n --arg query "$query" --argjson variables "$variables" \
|
|
73
|
+
'{query:$query, variables:$variables}' |
|
|
74
|
+
curl -sS -X POST "https://api.linear.app/graphql" \
|
|
75
|
+
-H "Content-Type: application/json" \
|
|
76
|
+
-H "Authorization: '"$LINEAR_API_KEY"'" \
|
|
77
|
+
--data-binary @-
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Map operation names to Linear GraphQL queries/mutations in this access skill.
|
|
82
|
+
Consumers pass business-shaped arguments only; they do not embed GraphQL.
|
|
83
|
+
|
|
84
|
+
## Invariants
|
|
85
|
+
|
|
86
|
+
- MCP is preferred when it is present and already authenticated.
|
|
87
|
+
- GraphQL fallback runs only when `LINEAR_API_KEY` is present.
|
|
88
|
+
- Missing MCP plus missing token is a hard failure naming `LINEAR_API_KEY`.
|
|
89
|
+
- Mutations send only the fields being changed, matching existing Linear skill
|
|
90
|
+
guidance that `save_*` style updates should not clobber unrelated fields.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: posthog-access
|
|
3
|
+
description: "Vendor-neutral access layer for PostHog. PostHog skills and observability rules MUST delegate through this skill rather than calling PostHog MCP tools or REST directly. Resolves PostHog MCP first when available, then falls back to POSTHOG_PERSONAL_API_KEY bearer auth."
|
|
4
|
+
allowed-tools: ["Bash", "Read", "Skill"]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# PostHog Access: $ARGUMENTS
|
|
8
|
+
|
|
9
|
+
Single chokepoint for PostHog operations. Caller skills and rules MUST NOT call
|
|
10
|
+
`mcp__posthog__*` tools or PostHog REST directly.
|
|
11
|
+
|
|
12
|
+
## Invocation Contract
|
|
13
|
+
|
|
14
|
+
```text
|
|
15
|
+
operation: query project_id:<ID> payload:{...}
|
|
16
|
+
operation: insights project_id:<ID>
|
|
17
|
+
operation: persons project_id:<ID> [query:<QUERY>]
|
|
18
|
+
operation: events project_id:<ID> [after:<ISO>] [before:<ISO>]
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Return parsed JSON in a `<result>` block.
|
|
22
|
+
|
|
23
|
+
## Substrate Selection
|
|
24
|
+
|
|
25
|
+
Probe in order:
|
|
26
|
+
|
|
27
|
+
1. PostHog MCP, if available and authenticated.
|
|
28
|
+
2. `POSTHOG_PERSONAL_API_KEY` bearer token against the configured PostHog host.
|
|
29
|
+
|
|
30
|
+
PostHog documents personal API keys and bearer authentication. The headless REST
|
|
31
|
+
tier uses:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
POSTHOG_HOST=${POSTHOG_HOST:-https://app.posthog.com}
|
|
35
|
+
posthog_api() {
|
|
36
|
+
local path="$1"
|
|
37
|
+
local method="${2:-GET}"
|
|
38
|
+
local body="${3:-}"
|
|
39
|
+
[ -n "$POSTHOG_PERSONAL_API_KEY" ] || {
|
|
40
|
+
echo "Error: POSTHOG_PERSONAL_API_KEY is not set." >&2
|
|
41
|
+
return 1
|
|
42
|
+
}
|
|
43
|
+
local args=(-sS -X "$method" -H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY")
|
|
44
|
+
[ -n "$body" ] && args+=(-H "Content-Type: application/json" --data-binary "$body")
|
|
45
|
+
curl "${args[@]}" "${POSTHOG_HOST%/}/api${path}"
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
If neither tier works, fail with:
|
|
50
|
+
|
|
51
|
+
```text
|
|
52
|
+
Error: no PostHog access substrate available. Authenticate the PostHog MCP or set POSTHOG_PERSONAL_API_KEY.
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Invariants
|
|
56
|
+
|
|
57
|
+
- Fallback is gated on `POSTHOG_PERSONAL_API_KEY`.
|
|
58
|
+
- `POSTHOG_HOST` defaults to PostHog Cloud but can point at a self-hosted
|
|
59
|
+
deployment.
|
|
60
|
+
- Consumer skills do not embed PostHog REST paths.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sentry-access
|
|
3
|
+
description: "Vendor-neutral access layer for Sentry. Sentry-oriented skills MUST delegate through this skill rather than calling Sentry MCP tools, sentry-cli, or REST directly. Resolves Sentry MCP/CLI first when available, then falls back to SENTRY_AUTH_TOKEN + Sentry REST API."
|
|
4
|
+
allowed-tools: ["Bash", "Read", "Skill"]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Sentry Access: $ARGUMENTS
|
|
8
|
+
|
|
9
|
+
Single chokepoint for Sentry operations. Caller skills MUST NOT call
|
|
10
|
+
`mcp__sentry__*`, `sentry-cli`, or `https://sentry.io/api/` directly.
|
|
11
|
+
|
|
12
|
+
## Invocation Contract
|
|
13
|
+
|
|
14
|
+
```text
|
|
15
|
+
operation: list-issues org:<ORG> project:<PROJECT> query:<QUERY> [environment:<ENV>]
|
|
16
|
+
operation: get-issue issue_id:<ID>
|
|
17
|
+
operation: events org:<ORG> project:<PROJECT> query:<QUERY>
|
|
18
|
+
operation: releases org:<ORG> project:<PROJECT>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Return parsed JSON in a `<result>` block.
|
|
22
|
+
|
|
23
|
+
## Substrate Selection
|
|
24
|
+
|
|
25
|
+
Probe in order:
|
|
26
|
+
|
|
27
|
+
1. Sentry MCP, if available and authenticated.
|
|
28
|
+
2. `sentry-cli`, if installed and authenticated to the requested org/project.
|
|
29
|
+
3. `SENTRY_AUTH_TOKEN` bearer token against Sentry REST.
|
|
30
|
+
|
|
31
|
+
Sentry documents API auth tokens for REST API calls. The headless REST tier uses:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
sentry_api() {
|
|
35
|
+
local path="$1"
|
|
36
|
+
[ -n "$SENTRY_AUTH_TOKEN" ] || {
|
|
37
|
+
echo "Error: SENTRY_AUTH_TOKEN is not set." >&2
|
|
38
|
+
return 1
|
|
39
|
+
}
|
|
40
|
+
curl -sS "https://sentry.io/api/0${path}" \
|
|
41
|
+
-H "Authorization: Bearer $SENTRY_AUTH_TOKEN"
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
If neither tier works, fail with:
|
|
46
|
+
|
|
47
|
+
```text
|
|
48
|
+
Error: no Sentry access substrate available. Authenticate Sentry MCP/CLI or set SENTRY_AUTH_TOKEN.
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Invariants
|
|
52
|
+
|
|
53
|
+
- Fallback is gated on `SENTRY_AUTH_TOKEN`.
|
|
54
|
+
- Org/project come from `.sentryclirc`, `.lisa.config.json`, or explicit
|
|
55
|
+
operation args; never infer by searching all accessible orgs.
|
|
56
|
+
- Consumer skills do not embed Sentry REST paths.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sonarcloud-access
|
|
3
|
+
description: "Vendor-neutral access layer for SonarCloud/SonarQube Cloud. Sonar triage skills MUST delegate through this skill rather than calling Sonar MCP tools or REST directly. Resolves Sonar MCP first when available, then falls back to SONAR_TOKEN + SonarCloud Web API."
|
|
4
|
+
allowed-tools: ["Bash", "Read", "Skill"]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# SonarCloud Access: $ARGUMENTS
|
|
8
|
+
|
|
9
|
+
Single chokepoint for SonarCloud operations. Caller skills MUST NOT call
|
|
10
|
+
`mcp__sonarqube__*` tools directly or curl `https://sonarcloud.io/api/`
|
|
11
|
+
themselves.
|
|
12
|
+
|
|
13
|
+
## Invocation Contract
|
|
14
|
+
|
|
15
|
+
```text
|
|
16
|
+
operation: gate-status project_key:<KEY> [branch:<BRANCH>] [pull_request:<N>]
|
|
17
|
+
operation: issues project_key:<KEY> [branch:<BRANCH>] [pull_request:<N>] [types:<csv>] [severities:<csv>]
|
|
18
|
+
operation: hotspots project_key:<KEY> [branch:<BRANCH>] [pull_request:<N>]
|
|
19
|
+
operation: rule-detail key:<RULE_KEY>
|
|
20
|
+
operation: source-snippet component:<COMPONENT_KEY> from:<N> to:<N>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Return parsed JSON in a `<result>` block.
|
|
24
|
+
|
|
25
|
+
## Substrate Selection
|
|
26
|
+
|
|
27
|
+
Probe in order:
|
|
28
|
+
|
|
29
|
+
1. Sonar MCP, if available and authenticated.
|
|
30
|
+
2. `SONAR_TOKEN` against the SonarCloud Web API.
|
|
31
|
+
|
|
32
|
+
SonarCloud documents bearer-token authentication for the Web API. Use:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
sonar_api() {
|
|
36
|
+
local path="$1"
|
|
37
|
+
[ -n "$SONAR_TOKEN" ] || {
|
|
38
|
+
echo "Error: SONAR_TOKEN is not set." >&2
|
|
39
|
+
return 1
|
|
40
|
+
}
|
|
41
|
+
curl -sS "https://sonarcloud.io/api${path}" \
|
|
42
|
+
-H "Authorization: Bearer $SONAR_TOKEN"
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
If a host still requires the legacy token-as-basic-auth form, make that an
|
|
47
|
+
explicit adapter branch in this skill; consumers do not choose auth style.
|
|
48
|
+
|
|
49
|
+
If neither tier works, fail with:
|
|
50
|
+
|
|
51
|
+
```text
|
|
52
|
+
Error: no SonarCloud access substrate available. Authenticate the Sonar MCP or set SONAR_TOKEN.
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## REST Dispatch
|
|
56
|
+
|
|
57
|
+
| Operation | REST path |
|
|
58
|
+
|---|---|
|
|
59
|
+
| `gate-status` | `/qualitygates/project_status?projectKey=<KEY>[&branch=<BRANCH>][&pullRequest=<N>]` |
|
|
60
|
+
| `issues` | `/issues/search?componentKeys=<KEY>[&branch=<BRANCH>][&pullRequest=<N>]...` |
|
|
61
|
+
| `hotspots` | `/hotspots/search?projectKey=<KEY>[&branch=<BRANCH>][&pullRequest=<N>]` |
|
|
62
|
+
| `rule-detail` | `/rules/show?key=<RULE_KEY>` |
|
|
63
|
+
| `source-snippet` | `/sources/lines?key=<COMPONENT_KEY>&from=<N>&to=<N>` |
|
|
64
|
+
|
|
65
|
+
## Invariants
|
|
66
|
+
|
|
67
|
+
- Fallback is gated on `SONAR_TOKEN`.
|
|
68
|
+
- SonarCloud host access requires `sonarcloud.io` in any custom remote network
|
|
69
|
+
allowlist.
|
|
70
|
+
- Consumers ask for analysis data by operation name; this skill owns the Web API
|
|
71
|
+
path shape.
|
|
@@ -191,12 +191,28 @@ const ACRONYMS = new Set([
|
|
|
191
191
|
"llm",
|
|
192
192
|
]);
|
|
193
193
|
|
|
194
|
+
/**
|
|
195
|
+
* Brand names whose mixed-case capitalization cannot be reproduced by the
|
|
196
|
+
* simple title-case or all-upper-case rules above.
|
|
197
|
+
*
|
|
198
|
+
* Keys are lower-cased token forms (as they appear split from a kebab skill
|
|
199
|
+
* name). Values are the canonical display spellings. Entries here take
|
|
200
|
+
* precedence over both {@link ACRONYMS} and the default title-case path so
|
|
201
|
+
* that `posthog-access` -> "PostHog Access" rather than "Posthog Access".
|
|
202
|
+
*/
|
|
203
|
+
const BRAND_NAMES = new Map([
|
|
204
|
+
["posthog", "PostHog"],
|
|
205
|
+
["sonarcloud", "SonarCloud"],
|
|
206
|
+
]);
|
|
207
|
+
|
|
194
208
|
/**
|
|
195
209
|
* Humanize a kebab/snake/space-delimited token into a Title-Cased display name.
|
|
196
210
|
*
|
|
197
211
|
* Splits on `-`, `_`, and runs of whitespace, then title-cases each word —
|
|
198
|
-
* except tokens in {@link ACRONYMS}, which are upper-cased
|
|
199
|
-
*
|
|
212
|
+
* except tokens in {@link ACRONYMS}, which are upper-cased, and tokens in
|
|
213
|
+
* {@link BRAND_NAMES}, which are emitted with their canonical spelling.
|
|
214
|
+
* This is the rule the PRD (#521) specifies for `display_name`:
|
|
215
|
+
* `exploratory-qa` -> "Exploratory QA".
|
|
200
216
|
* Pure: same input always yields the same output.
|
|
201
217
|
*
|
|
202
218
|
* @param {string} raw The raw skill/frontmatter name token.
|
|
@@ -206,11 +222,16 @@ function humanizeName(raw) {
|
|
|
206
222
|
return raw
|
|
207
223
|
.split(/[-_\s]+/)
|
|
208
224
|
.filter(word => word.length > 0)
|
|
209
|
-
.map(word =>
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
225
|
+
.map(word => {
|
|
226
|
+
const lower = word.toLowerCase();
|
|
227
|
+
if (BRAND_NAMES.has(lower)) {
|
|
228
|
+
return BRAND_NAMES.get(lower);
|
|
229
|
+
}
|
|
230
|
+
if (ACRONYMS.has(lower)) {
|
|
231
|
+
return word.toUpperCase();
|
|
232
|
+
}
|
|
233
|
+
return word.charAt(0).toUpperCase() + word.slice(1);
|
|
234
|
+
})
|
|
214
235
|
.join(" ");
|
|
215
236
|
}
|
|
216
237
|
|