@codyswann/lisa 2.37.0 → 2.39.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/skills/acceptance-criteria/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/agent-design-best-practices/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/atlassian-access/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/bug-triage/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/codebase-research/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/codify-verification/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/confluence-prd-intake/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/confluence-to-tracker/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/debrief/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/debrief-apply/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/epic-triage/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/fix-linter-error/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/git-commit/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/git-prune/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/git-submit-pr/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/github-add-journey/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/github-build-intake/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/github-create/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/github-evidence/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/github-journey/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/github-prd-intake/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/github-read-issue/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/github-sync/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/github-to-tracker/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/github-validate-issue/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/github-verify/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/github-write-issue/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/implement/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/improve-code-complexity/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/improve-max-lines/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/improve-max-lines-per-function/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/improve-test-coverage/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/improve-tests/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/intake/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/jira-add-journey/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/jira-build-intake/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/jira-create/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/jira-evidence/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/jira-journey/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/jira-read-ticket/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/jira-sync/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/jira-validate-ticket/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/jira-verify/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/jira-write-ticket/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/jsdoc-best-practices/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/linear-add-journey/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/linear-build-intake/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/linear-create/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/linear-evidence/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/linear-journey/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/linear-prd-intake/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/linear-read-issue/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/linear-sync/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/linear-to-tracker/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/linear-validate-issue/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/linear-verify/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/linear-write-issue/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/lisa-review-implementation/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/monitor/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/nightly-add-test-coverage/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/nightly-improve-tests/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/nightly-lower-code-complexity/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/notion-access/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/notion-prd-intake/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/notion-to-tracker/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/performance-review/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/plan/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/prd-backlink/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/prd-ticket-coverage/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/product-walkthrough/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/pull-request-review/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/quality-review/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/reproduce-bug/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/research/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/review-local/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/root-cause-analysis/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/security-review/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/security-zap-scan/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/setup-atlassian/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/setup-confluence/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/setup-github/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/setup-jira/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/setup-linear/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/setup-notion/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/spec-conformance/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/task-decomposition/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/task-triage/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/tdd-implementation/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/test-strategy/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/ticket-triage/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/tracker-add-journey/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/tracker-build-intake/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/tracker-create/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/tracker-evidence/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/tracker-journey/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/tracker-read/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/tracker-source-artifacts/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/tracker-sync/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/tracker-validate/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/tracker-verify/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/tracker-write/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/verification-lifecycle/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/verify/agents/openai.yaml +4 -0
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/skills/apollo-client/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/atomic-design-gluestack/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/container-view-pattern/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/cross-platform-compatibility/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/directory-structure/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/exploratory-qa/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/expo-env-config/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/expo-router-best-practices/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/gluestack-nativewind/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/jira-add-journey/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/jira-create/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/jira-evidence/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/jira-journey/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/jira-verify/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/local-state/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/ops-browser-uat/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/ops-check-logs/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/ops-db-ops/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/ops-deploy/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/ops-monitor-errors/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/ops-performance/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/ops-run-local/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/ops-verify-health/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/owasp-zap/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/playwright-ci-debugging/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/playwright-selectors/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/reduce-complexity/agents/openai.yaml +4 -0
- package/plugins/lisa-expo/skills/testing-library/agents/openai.yaml +4 -0
- 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/skills/exploratory-qa/agents/openai.yaml +4 -0
- package/plugins/lisa-harper-fabric/skills/harper-build-and-deploy/agents/openai.yaml +4 -0
- package/plugins/lisa-harper-fabric/skills/harper-component-model/agents/openai.yaml +4 -0
- package/plugins/lisa-harper-fabric/skills/harper-config-yaml/agents/openai.yaml +4 -0
- package/plugins/lisa-harper-fabric/skills/harper-resources/agents/openai.yaml +4 -0
- package/plugins/lisa-harper-fabric/skills/harper-schema-graphql/agents/openai.yaml +4 -0
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/skills/nestjs-graphql/agents/openai.yaml +4 -0
- package/plugins/lisa-nestjs/skills/nestjs-rules/agents/openai.yaml +4 -0
- package/plugins/lisa-nestjs/skills/typeorm-patterns/agents/openai.yaml +4 -0
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/skills/lisa-openclaw-connect-repo-topic/agents/openai.yaml +4 -0
- package/plugins/lisa-openclaw/skills/lisa-openclaw-connect-staff/agents/openai.yaml +4 -0
- package/plugins/lisa-openclaw/skills/lisa-openclaw-setup/agents/openai.yaml +4 -0
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/skills/action-controller-best-practices/agents/openai.yaml +4 -0
- package/plugins/lisa-rails/skills/action-view-best-practices/agents/openai.yaml +4 -0
- package/plugins/lisa-rails/skills/active-record-model-best-practices/agents/openai.yaml +4 -0
- package/plugins/lisa-rails/skills/exploratory-qa/agents/openai.yaml +4 -0
- package/plugins/lisa-rails/skills/fix-linter-error/agents/openai.yaml +4 -0
- package/plugins/lisa-rails/skills/improve-code-complexity/agents/openai.yaml +4 -0
- package/plugins/lisa-rails/skills/improve-max-lines/agents/openai.yaml +4 -0
- package/plugins/lisa-rails/skills/improve-max-lines-per-function/agents/openai.yaml +4 -0
- package/plugins/lisa-rails/skills/improve-test-coverage/agents/openai.yaml +4 -0
- package/plugins/lisa-rails/skills/jira-add-journey/agents/openai.yaml +4 -0
- package/plugins/lisa-rails/skills/jira-create/agents/openai.yaml +4 -0
- package/plugins/lisa-rails/skills/jira-evidence/agents/openai.yaml +4 -0
- package/plugins/lisa-rails/skills/jira-journey/agents/openai.yaml +4 -0
- package/plugins/lisa-rails/skills/jira-verify/agents/openai.yaml +4 -0
- package/plugins/lisa-rails/skills/ops-check-logs/agents/openai.yaml +4 -0
- package/plugins/lisa-rails/skills/ops-deploy/agents/openai.yaml +4 -0
- package/plugins/lisa-rails/skills/ops-run-local/agents/openai.yaml +4 -0
- package/plugins/lisa-rails/skills/ops-verify-jobs/agents/openai.yaml +4 -0
- package/plugins/lisa-rails/skills/ops-verify-telemetry/agents/openai.yaml +4 -0
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-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/skills/lisa-wiki-add-ingest/agents/openai.yaml +4 -0
- package/plugins/lisa-wiki/skills/lisa-wiki-add-role/agents/openai.yaml +4 -0
- package/plugins/lisa-wiki/skills/lisa-wiki-connector-confluence/agents/openai.yaml +4 -0
- package/plugins/lisa-wiki/skills/lisa-wiki-connector-docs/agents/openai.yaml +4 -0
- package/plugins/lisa-wiki/skills/lisa-wiki-connector-git/agents/openai.yaml +4 -0
- package/plugins/lisa-wiki/skills/lisa-wiki-connector-jira/agents/openai.yaml +4 -0
- package/plugins/lisa-wiki/skills/lisa-wiki-connector-memory/agents/openai.yaml +4 -0
- package/plugins/lisa-wiki/skills/lisa-wiki-connector-notion/agents/openai.yaml +4 -0
- package/plugins/lisa-wiki/skills/lisa-wiki-connector-roles/agents/openai.yaml +4 -0
- package/plugins/lisa-wiki/skills/lisa-wiki-connector-slack/agents/openai.yaml +4 -0
- package/plugins/lisa-wiki/skills/lisa-wiki-connector-web/agents/openai.yaml +4 -0
- package/plugins/lisa-wiki/skills/lisa-wiki-doctor/agents/openai.yaml +4 -0
- package/plugins/lisa-wiki/skills/lisa-wiki-ingest/agents/openai.yaml +4 -0
- package/plugins/lisa-wiki/skills/lisa-wiki-lint/agents/openai.yaml +4 -0
- package/plugins/lisa-wiki/skills/lisa-wiki-migrate/agents/openai.yaml +4 -0
- package/plugins/lisa-wiki/skills/lisa-wiki-onboard-me/agents/openai.yaml +4 -0
- package/plugins/lisa-wiki/skills/lisa-wiki-query/agents/openai.yaml +4 -0
- package/plugins/lisa-wiki/skills/lisa-wiki-setup/agents/openai.yaml +4 -0
- package/plugins/lisa-wiki/skills/lisa-wiki-usage/agents/openai.yaml +4 -0
- package/scripts/generate-codex-plugin-artifacts.mjs +216 -0
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
display_name: "Lisa Wiki Add Ingest"
|
|
2
|
+
short_description: "Scaffold a project-specific \"front-door\" ingest skill that does something unique (classify a source, fetch from a special system, stamp…"
|
|
3
|
+
default_prompt:
|
|
4
|
+
- "Use $lisa-wiki-add-ingest: Scaffold a project-specific \"front-door\" ingest skill that does something unique (classify a source, fetch from a special system, stamp…."
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
display_name: "Lisa Wiki Add Role"
|
|
2
|
+
short_description: "Scaffold a domain-expert \"digital staff\" role over the wiki — a dual-runtime subagent (Claude + Codex) plus a staff doc page — from a…"
|
|
3
|
+
default_prompt:
|
|
4
|
+
- "Use $lisa-wiki-add-role: Scaffold a domain-expert \"digital staff\" role over the wiki — a dual-runtime subagent (Claude + Codex) plus a staff doc page — from a…."
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
display_name: "Lisa Wiki Connector Confluence"
|
|
2
|
+
short_description: "Produce sanitized Confluence source notes for lisa-wiki ingest via the Atlassian MCP"
|
|
3
|
+
default_prompt:
|
|
4
|
+
- "Use $lisa-wiki-connector-confluence: Produce sanitized Confluence source notes for lisa-wiki ingest via the Atlassian MCP."
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
display_name: "Lisa Wiki Connector Docs"
|
|
2
|
+
short_description: "Ingest a local document (PDF, DOCX, Markdown, text) into a sanitized source note for lisa-wiki ingest"
|
|
3
|
+
default_prompt:
|
|
4
|
+
- "Use $lisa-wiki-connector-docs: Ingest a local document (PDF, DOCX, Markdown, text) into a sanitized source note for lisa-wiki ingest."
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
display_name: "Lisa Wiki Connector Jira"
|
|
2
|
+
short_description: "Produce sanitized JIRA source notes for lisa-wiki ingest via the Atlassian MCP"
|
|
3
|
+
default_prompt:
|
|
4
|
+
- "Use $lisa-wiki-connector-jira: Produce sanitized JIRA source notes for lisa-wiki ingest via the Atlassian MCP."
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
display_name: "Lisa Wiki Connector Notion"
|
|
2
|
+
short_description: "Produce sanitized Notion source notes for lisa-wiki ingest via the Notion MCP"
|
|
3
|
+
default_prompt:
|
|
4
|
+
- "Use $lisa-wiki-connector-notion: Produce sanitized Notion source notes for lisa-wiki ingest via the Notion MCP."
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
display_name: "Lisa Wiki Connector Roles"
|
|
2
|
+
short_description: "Ingest the wiki's own digital-staff roster (config.staff[] + wiki/staff/*) into a sanitized source note"
|
|
3
|
+
default_prompt:
|
|
4
|
+
- "Use $lisa-wiki-connector-roles: Ingest the wiki's own digital-staff roster (config.staff[] + wiki/staff/*) into a sanitized source note."
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
display_name: "Lisa Wiki Connector Web"
|
|
2
|
+
short_description: "Ingest a public URL into a sanitized source note for lisa-wiki ingest (via WebFetch)"
|
|
3
|
+
default_prompt:
|
|
4
|
+
- "Use $lisa-wiki-connector-web: Ingest a public URL into a sanitized source note for lisa-wiki ingest (via WebFetch)."
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
display_name: "Lisa Wiki Migrate"
|
|
2
|
+
short_description: "Migrate an existing, hand-rolled wiki implementation onto the lisa-wiki kernel — phased and compatibility-first, with a strict no-loss…"
|
|
3
|
+
default_prompt:
|
|
4
|
+
- "Use $lisa-wiki-migrate: Migrate an existing, hand-rolled wiki implementation onto the lisa-wiki kernel — phased and compatibility-first, with a strict no-loss…."
|
|
@@ -123,6 +123,221 @@ export function serializeInterfaceToYaml(iface) {
|
|
|
123
123
|
return `${lines.join("\n")}\n`;
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
+
/**
|
|
127
|
+
* Acronyms that should stay fully upper-cased when a skill name is humanized.
|
|
128
|
+
*
|
|
129
|
+
* Skill names are kebab/snake tokens (e.g. `exploratory-qa`); naive title-casing
|
|
130
|
+
* would yield "Qa". Tokens listed here (compared case-insensitively) are emitted
|
|
131
|
+
* upper-case instead so `exploratory-qa` -> "Exploratory QA". The set is small and
|
|
132
|
+
* deliberately conservative — only well-known initialisms that appear in Lisa
|
|
133
|
+
* skill names — so humanization stays a pure, predictable function of the input.
|
|
134
|
+
*/
|
|
135
|
+
const ACRONYMS = new Set([
|
|
136
|
+
"qa",
|
|
137
|
+
"ci",
|
|
138
|
+
"cd",
|
|
139
|
+
"pr",
|
|
140
|
+
"prd",
|
|
141
|
+
"ui",
|
|
142
|
+
"ux",
|
|
143
|
+
"api",
|
|
144
|
+
"cli",
|
|
145
|
+
"sdk",
|
|
146
|
+
"tdd",
|
|
147
|
+
"mcp",
|
|
148
|
+
"aws",
|
|
149
|
+
"cdk",
|
|
150
|
+
"zap",
|
|
151
|
+
"owasp",
|
|
152
|
+
"sql",
|
|
153
|
+
"url",
|
|
154
|
+
"id",
|
|
155
|
+
"io",
|
|
156
|
+
"llm",
|
|
157
|
+
]);
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Humanize a kebab/snake/space-delimited token into a Title-Cased display name.
|
|
161
|
+
*
|
|
162
|
+
* Splits on `-`, `_`, and runs of whitespace, then title-cases each word —
|
|
163
|
+
* except tokens in {@link ACRONYMS}, which are upper-cased. This is the rule the
|
|
164
|
+
* PRD (#521) specifies for `display_name`: `exploratory-qa` -> "Exploratory QA".
|
|
165
|
+
* Pure: same input always yields the same output.
|
|
166
|
+
*
|
|
167
|
+
* @param {string} raw The raw skill/frontmatter name token.
|
|
168
|
+
* @returns {string} The humanized, title-cased display name.
|
|
169
|
+
*/
|
|
170
|
+
function humanizeName(raw) {
|
|
171
|
+
return raw
|
|
172
|
+
.split(/[-_\s]+/)
|
|
173
|
+
.filter(word => word.length > 0)
|
|
174
|
+
.map(word =>
|
|
175
|
+
ACRONYMS.has(word.toLowerCase())
|
|
176
|
+
? word.toUpperCase()
|
|
177
|
+
: word.charAt(0).toUpperCase() + word.slice(1)
|
|
178
|
+
)
|
|
179
|
+
.join(" ");
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Boilerplate openings that several Lisa skill descriptions share (e.g. "This
|
|
184
|
+
* skill should be used when ..."). They add no signal to a short UI summary, so
|
|
185
|
+
* the leading phrase is stripped before the first-sentence summary is taken.
|
|
186
|
+
* Matched case-insensitively at the very start of the description only.
|
|
187
|
+
*/
|
|
188
|
+
const DESCRIPTION_PREFIXES = [
|
|
189
|
+
/^this skill should be used (when|to|for|whenever|any time|anytime|while)\s+/i,
|
|
190
|
+
/^this skill should be used\s+/i,
|
|
191
|
+
/^use this skill (when|to|for|whenever|any time|anytime|while)\s+/i,
|
|
192
|
+
/^use when\s+/i,
|
|
193
|
+
];
|
|
194
|
+
|
|
195
|
+
/** Upper bound on the derived `short_description` length (characters). */
|
|
196
|
+
const SHORT_DESCRIPTION_MAX = 140;
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Derive a concise `short_description` from a skill's full frontmatter
|
|
200
|
+
* `description`.
|
|
201
|
+
*
|
|
202
|
+
* DERIVATION RULE (Epic Open Question — "use best judgement based on the context
|
|
203
|
+
* of the project", per the PRD #521 author): a Lisa skill description leads with
|
|
204
|
+
* a one-line summary and then enumerates trigger conditions across several
|
|
205
|
+
* sentences. The concise summary is therefore the first sentence:
|
|
206
|
+
*
|
|
207
|
+
* 1. Strip a leading "This skill should be used when/to/for ..." boilerplate
|
|
208
|
+
* prefix (see {@link DESCRIPTION_PREFIXES}) so the summary carries signal.
|
|
209
|
+
* 2. Take the text up to the first sentence terminator (`. `, `! `, `? `).
|
|
210
|
+
* 3. Trim a trailing period and clamp to {@link SHORT_DESCRIPTION_MAX} chars
|
|
211
|
+
* (word-boundary truncation with an ellipsis) so it stays a *short*
|
|
212
|
+
* description.
|
|
213
|
+
*
|
|
214
|
+
* For `exploratory-qa` this yields "Playwright-backed exploratory QA workflow
|
|
215
|
+
* for web apps", matching the PRD's hand-written example shape.
|
|
216
|
+
*
|
|
217
|
+
* @param {string} description The full (trimmed) frontmatter description.
|
|
218
|
+
* @returns {string} A concise one-line summary (may be empty if input is empty).
|
|
219
|
+
*/
|
|
220
|
+
function summarizeDescription(description) {
|
|
221
|
+
if (description === "") {
|
|
222
|
+
return "";
|
|
223
|
+
}
|
|
224
|
+
const deboilerplated = DESCRIPTION_PREFIXES.reduce(
|
|
225
|
+
(text, prefix) => text.replace(prefix, ""),
|
|
226
|
+
description
|
|
227
|
+
).trim();
|
|
228
|
+
// First sentence: stop at the first `.`, `!`, or `?` that is followed by
|
|
229
|
+
// whitespace or end-of-string (so "e2e" / "U.S." mid-sentence don't split).
|
|
230
|
+
const sentenceMatch = /^(.*?[.!?])(?:\s|$)/.exec(deboilerplated);
|
|
231
|
+
const firstSentence = (
|
|
232
|
+
sentenceMatch ? sentenceMatch[1] : deboilerplated
|
|
233
|
+
).replace(/[.\s]+$/, "");
|
|
234
|
+
if (firstSentence.length <= SHORT_DESCRIPTION_MAX) {
|
|
235
|
+
return firstSentence;
|
|
236
|
+
}
|
|
237
|
+
const clamped = firstSentence.slice(0, SHORT_DESCRIPTION_MAX);
|
|
238
|
+
const lastSpace = clamped.lastIndexOf(" ");
|
|
239
|
+
const truncated = lastSpace > 0 ? clamped.slice(0, lastSpace) : clamped;
|
|
240
|
+
return `${truncated.replace(/[,;:.\s]+$/, "")}…`;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Derive a Codex `interface` object from a skill's SKILL.md frontmatter.
|
|
245
|
+
*
|
|
246
|
+
* DERIVATION RULES (issue #548; the Epic Open Question asked the author for the
|
|
247
|
+
* `short_description`/`default_prompt` rule and the guidance was "use best
|
|
248
|
+
* judgement based on the context of the project"):
|
|
249
|
+
*
|
|
250
|
+
* - `display_name` — {@link humanizeName} of `frontmatter.name`: title-cased,
|
|
251
|
+
* with known acronyms upper-cased (`exploratory-qa` -> "Exploratory QA").
|
|
252
|
+
* - `short_description` — {@link summarizeDescription} of `frontmatter.description`:
|
|
253
|
+
* the boilerplate-stripped first sentence, clamped to a short length.
|
|
254
|
+
* - `default_prompt` — a single short starter prompt that references the skill
|
|
255
|
+
* token `$<name>` (the canonical kebab name, not the humanized one, because
|
|
256
|
+
* Codex invokes skills by their `$<name>` token). When a summary is available
|
|
257
|
+
* the prompt reads "Use $<name>: <summary>." — a colon join is used rather
|
|
258
|
+
* than "Use $<name> to <summary>" because a derived summary may be a noun
|
|
259
|
+
* phrase ("Playwright-backed exploratory QA workflow") rather than a verb
|
|
260
|
+
* clause, and "... to <noun phrase>" reads awkwardly. The colon form is
|
|
261
|
+
* grammatical for either shape. When there is no description it falls back to
|
|
262
|
+
* a bare "Use $<name>". The `$<name>` token is always present — the
|
|
263
|
+
* acceptance criterion.
|
|
264
|
+
*
|
|
265
|
+
* Falls back to the skill directory name (and an empty description) when the
|
|
266
|
+
* frontmatter is missing, so every skill still emits a well-formed file. Pure:
|
|
267
|
+
* no I/O, deterministic output for deterministic input.
|
|
268
|
+
*
|
|
269
|
+
* @param {{ name?: string, description?: string } | null} frontmatter Parsed
|
|
270
|
+
* SKILL.md frontmatter (or `null` when the file has no frontmatter block).
|
|
271
|
+
* @param {string} skillName The skill directory name, used as a fallback.
|
|
272
|
+
* @returns {{ display_name: string, short_description: string, default_prompt: string[] }}
|
|
273
|
+
* The normalized interface object the serializer consumes.
|
|
274
|
+
*/
|
|
275
|
+
export function deriveSkillInterface(frontmatter, skillName) {
|
|
276
|
+
const name = frontmatter?.name?.trim() || skillName;
|
|
277
|
+
const description = frontmatter?.description?.trim() || "";
|
|
278
|
+
const shortDescription = summarizeDescription(description);
|
|
279
|
+
const starter =
|
|
280
|
+
shortDescription === ""
|
|
281
|
+
? `Use $${name}`
|
|
282
|
+
: `Use $${name}: ${shortDescription}.`;
|
|
283
|
+
return {
|
|
284
|
+
display_name: humanizeName(name),
|
|
285
|
+
short_description: shortDescription,
|
|
286
|
+
default_prompt: [starter],
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Walk every `skills/<name>/SKILL.md` in a built plugin and emit a per-skill
|
|
292
|
+
* `skills/<name>/agents/openai.yaml` (issue #547).
|
|
293
|
+
*
|
|
294
|
+
* For each skill directory containing a SKILL.md, the frontmatter is parsed
|
|
295
|
+
* (#545), an interface object is derived via {@link deriveSkillInterface} (#548),
|
|
296
|
+
* and the deterministic serializer (#546) writes `agents/openai.yaml`, creating
|
|
297
|
+
* the `agents/` directory when missing. Behavior boundaries:
|
|
298
|
+
*
|
|
299
|
+
* - No-op when the plugin has no `skills/` directory.
|
|
300
|
+
* - Never clobber a hand-authored `agents/openai.yaml` that already exists in
|
|
301
|
+
* source (that is issue #550's surface — but we must not overwrite it here
|
|
302
|
+
* regardless).
|
|
303
|
+
* - The `commands/` directory is left untouched — Codex does not consume Claude
|
|
304
|
+
* `commands/`.
|
|
305
|
+
*
|
|
306
|
+
* @param {string} pluginDir Absolute path to a built plugin directory.
|
|
307
|
+
* @returns {void} Writes files as a side effect.
|
|
308
|
+
*/
|
|
309
|
+
export function writeSkillAgents(pluginDir) {
|
|
310
|
+
const skillsDir = path.join(pluginDir, "skills");
|
|
311
|
+
if (!fs.existsSync(skillsDir)) {
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
const entries = fs
|
|
316
|
+
.readdirSync(skillsDir, { withFileTypes: true })
|
|
317
|
+
.filter(entry => entry.isDirectory())
|
|
318
|
+
.map(entry => entry.name)
|
|
319
|
+
.sort();
|
|
320
|
+
|
|
321
|
+
for (const skillName of entries) {
|
|
322
|
+
const skillDir = path.join(skillsDir, skillName);
|
|
323
|
+
const skillMdPath = path.join(skillDir, "SKILL.md");
|
|
324
|
+
if (!fs.existsSync(skillMdPath)) {
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const openaiYamlPath = path.join(skillDir, "agents", "openai.yaml");
|
|
329
|
+
// Don't clobber a hand-authored openai.yaml carried over from source.
|
|
330
|
+
if (fs.existsSync(openaiYamlPath)) {
|
|
331
|
+
continue;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
const frontmatter = parseSkillFrontmatter(skillMdPath);
|
|
335
|
+
const iface = deriveSkillInterface(frontmatter, skillName);
|
|
336
|
+
fs.mkdirSync(path.dirname(openaiYamlPath), { recursive: true });
|
|
337
|
+
fs.writeFileSync(openaiYamlPath, serializeInterfaceToYaml(iface));
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
126
341
|
function main() {
|
|
127
342
|
const [pluginDirArg, versionArg] = process.argv.slice(2);
|
|
128
343
|
if (!pluginDirArg || !versionArg) {
|
|
@@ -148,6 +363,7 @@ function main() {
|
|
|
148
363
|
const pluginName = claudeManifest.name;
|
|
149
364
|
|
|
150
365
|
writeCodexManifest(pluginDir, claudeManifest, pluginName, versionArg);
|
|
366
|
+
writeSkillAgents(pluginDir);
|
|
151
367
|
}
|
|
152
368
|
|
|
153
369
|
function writeCodexManifest(pluginDir, claudeManifest, pluginName, version) {
|