@codyswann/lisa 2.176.11 → 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.
Files changed (96) hide show
  1. package/dist/codex/scripts/setup-jira-cli.sh +34 -0
  2. package/dist/opencode/plugin-templates/lisa-session-bootstrap.ts +34 -4
  3. package/package.json +1 -1
  4. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  5. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  6. package/plugins/lisa/hooks/setup-jira-cli.sh +36 -2
  7. package/plugins/lisa/rules/eager/integration-access-layer.md +10 -0
  8. package/plugins/lisa/rules/reference/integration-access-layer.md +56 -0
  9. package/plugins/lisa/skills/jam-access/SKILL.md +51 -0
  10. package/plugins/lisa/skills/jam-access/agents/openai.yaml +4 -0
  11. package/plugins/lisa/skills/linear-access/SKILL.md +90 -0
  12. package/plugins/lisa/skills/linear-access/agents/openai.yaml +4 -0
  13. package/plugins/lisa/skills/posthog-access/SKILL.md +60 -0
  14. package/plugins/lisa/skills/posthog-access/agents/openai.yaml +4 -0
  15. package/plugins/lisa/skills/sentry-access/SKILL.md +56 -0
  16. package/plugins/lisa/skills/sentry-access/agents/openai.yaml +4 -0
  17. package/plugins/lisa/skills/sonarcloud-access/SKILL.md +71 -0
  18. package/plugins/lisa/skills/sonarcloud-access/agents/openai.yaml +4 -0
  19. package/plugins/lisa-agy/plugin.json +1 -1
  20. package/plugins/lisa-agy/skills/jam-access/SKILL.md +51 -0
  21. package/plugins/lisa-agy/skills/linear-access/SKILL.md +90 -0
  22. package/plugins/lisa-agy/skills/posthog-access/SKILL.md +60 -0
  23. package/plugins/lisa-agy/skills/sentry-access/SKILL.md +56 -0
  24. package/plugins/lisa-agy/skills/sonarcloud-access/SKILL.md +71 -0
  25. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  26. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  27. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  28. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  29. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  30. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  31. package/plugins/lisa-copilot/hooks/setup-jira-cli.sh +36 -2
  32. package/plugins/lisa-copilot/rules/eager/integration-access-layer.md +10 -0
  33. package/plugins/lisa-copilot/rules/reference/integration-access-layer.md +56 -0
  34. package/plugins/lisa-copilot/skills/jam-access/SKILL.md +51 -0
  35. package/plugins/lisa-copilot/skills/linear-access/SKILL.md +90 -0
  36. package/plugins/lisa-copilot/skills/posthog-access/SKILL.md +60 -0
  37. package/plugins/lisa-copilot/skills/sentry-access/SKILL.md +56 -0
  38. package/plugins/lisa-copilot/skills/sonarcloud-access/SKILL.md +71 -0
  39. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  40. package/plugins/lisa-cursor/hooks/setup-jira-cli.sh +36 -2
  41. package/plugins/lisa-cursor/rules/integration-access-layer-reference.mdc +61 -0
  42. package/plugins/lisa-cursor/rules/integration-access-layer.mdc +15 -0
  43. package/plugins/lisa-cursor/skills/jam-access/SKILL.md +51 -0
  44. package/plugins/lisa-cursor/skills/linear-access/SKILL.md +90 -0
  45. package/plugins/lisa-cursor/skills/posthog-access/SKILL.md +60 -0
  46. package/plugins/lisa-cursor/skills/sentry-access/SKILL.md +56 -0
  47. package/plugins/lisa-cursor/skills/sonarcloud-access/SKILL.md +71 -0
  48. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  49. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  50. package/plugins/lisa-expo-agy/plugin.json +1 -1
  51. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  52. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  53. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  54. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  55. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  56. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  57. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  58. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  59. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  60. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  61. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  62. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  63. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  64. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  65. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  66. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  67. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  68. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  69. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  70. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  71. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  72. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  73. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  74. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  75. package/plugins/lisa-rails-agy/plugin.json +1 -1
  76. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  77. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  78. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  79. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  80. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  81. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  82. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  83. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  84. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  85. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  86. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  87. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  88. package/plugins/src/base/hooks/setup-jira-cli.sh +36 -2
  89. package/plugins/src/base/rules/eager/integration-access-layer.md +10 -0
  90. package/plugins/src/base/rules/reference/integration-access-layer.md +56 -0
  91. package/plugins/src/base/skills/jam-access/SKILL.md +51 -0
  92. package/plugins/src/base/skills/linear-access/SKILL.md +90 -0
  93. package/plugins/src/base/skills/posthog-access/SKILL.md +60 -0
  94. package/plugins/src/base/skills/sentry-access/SKILL.md +56 -0
  95. package/plugins/src/base/skills/sonarcloud-access/SKILL.md +71 -0
  96. package/scripts/generate-codex-plugin-artifacts.mjs +28 -7
@@ -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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.176.11",
3
+ "version": "2.177.0",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.176.11",
3
+ "version": "2.177.0",
4
4
  "description": "AWS CDK-specific Lisa plugin.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.176.11",
3
+ "version": "2.177.0",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.176.11",
3
+ "version": "2.177.0",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.176.11",
3
+ "version": "2.177.0",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.176.11",
3
+ "version": "2.177.0",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -5,9 +5,9 @@
5
5
  #
6
6
  # Required env vars (must be created in your Claude Code Web environment):
7
7
  # JIRA_INSTALLATION - cloud or local
8
- # JIRA_SERVER - Atlassian instance URL
8
+ # JIRA_SERVER - Atlassian instance URL (falls back to .lisa.config*.json atlassian.site)
9
9
  # JIRA_LOGIN - login email
10
- # JIRA_PROJECT - default project key
10
+ # JIRA_PROJECT - default project key (falls back to .lisa.config*.json jira.project)
11
11
  # JIRA_API_TOKEN - already expected by jira-cli natively
12
12
  #
13
13
  # Optional env vars:
@@ -31,6 +31,40 @@ fi
31
31
  CONFIG_DIR="${HOME}/.config/.jira"
32
32
  CONFIG_FILE="${CONFIG_DIR}/.config.yml"
33
33
 
34
+ read_lisa_config() {
35
+ local query="$1"
36
+ local value=""
37
+
38
+ if ! command -v jq &>/dev/null; then
39
+ return 0
40
+ fi
41
+
42
+ if [[ -f ".lisa.config.local.json" ]]; then
43
+ value=$(jq -r "${query} // empty" .lisa.config.local.json 2>/dev/null || true)
44
+ fi
45
+
46
+ if [[ -z "${value}" && -f ".lisa.config.json" ]]; then
47
+ value=$(jq -r "${query} // empty" .lisa.config.json 2>/dev/null || true)
48
+ fi
49
+
50
+ printf '%s' "${value}"
51
+ }
52
+
53
+ if [[ -z "${JIRA_SERVER:-}" ]]; then
54
+ ATLASSIAN_SITE="$(read_lisa_config '.atlassian.site')"
55
+ if [[ -n "${ATLASSIAN_SITE}" ]]; then
56
+ if [[ "${ATLASSIAN_SITE}" == http://* || "${ATLASSIAN_SITE}" == https://* ]]; then
57
+ JIRA_SERVER="${ATLASSIAN_SITE}"
58
+ else
59
+ JIRA_SERVER="https://${ATLASSIAN_SITE}"
60
+ fi
61
+ fi
62
+ fi
63
+
64
+ if [[ -z "${JIRA_PROJECT:-}" ]]; then
65
+ JIRA_PROJECT="$(read_lisa_config '.jira.project')"
66
+ fi
67
+
34
68
  # Skip config write if required vars are missing
35
69
  if [[ -z "${JIRA_SERVER:-}" || -z "${JIRA_LOGIN:-}" ]]; then
36
70
  exit 0
@@ -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.