@codyswann/lisa 4.74.9 → 4.75.1
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/.claude-plugin/marketplace.json +60 -0
- package/all/copy-overwrite/scripts/lib/npm-update-github.mjs +73 -40
- package/all/copy-overwrite/scripts/lib/npm-update-invariants.mjs +54 -0
- package/all/copy-overwrite/scripts/npm-updater-helper-graph.json +3 -2
- package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.js +6 -0
- package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
- package/dist/core/lisa-skill-sources.d.ts +3 -3
- package/dist/core/lisa-skill-sources.d.ts.map +1 -1
- package/dist/core/lisa-skill-sources.js +3 -2
- package/dist/core/lisa-skill-sources.js.map +1 -1
- package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +735 -8
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/package.json +4 -4
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-agy/plugin.json +1 -1
- 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-cdk-devin/.claude-plugin/plugin.json +11 -0
- package/plugins/lisa-cdk-devin/.devin-plugin/plugin.json +8 -0
- package/plugins/lisa-cdk-devin/skills/setup-aws-accounts/SKILL.md +292 -0
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-devin/.claude-plugin/plugin.json +8 -0
- package/plugins/lisa-devin/.devin-plugin/plugin.json +8 -0
- package/plugins/lisa-devin/.mcp.json +8 -0
- package/plugins/lisa-devin/agents/architecture-specialist.md +32 -0
- package/plugins/lisa-devin/agents/bug-fixer.md +43 -0
- package/plugins/lisa-devin/agents/builder.md +44 -0
- package/plugins/lisa-devin/agents/confluence-prd-intake.md +65 -0
- package/plugins/lisa-devin/agents/debug-specialist.md +34 -0
- package/plugins/lisa-devin/agents/eval-specialist.md +33 -0
- package/plugins/lisa-devin/agents/git-history-analyzer.md +183 -0
- package/plugins/lisa-devin/agents/github-agent.md +155 -0
- package/plugins/lisa-devin/agents/github-build-intake.md +64 -0
- package/plugins/lisa-devin/agents/github-prd-intake.md +66 -0
- package/plugins/lisa-devin/agents/jira-agent.md +135 -0
- package/plugins/lisa-devin/agents/jira-build-intake.md +64 -0
- package/plugins/lisa-devin/agents/learner.md +85 -0
- package/plugins/lisa-devin/agents/learning-judge.md +119 -0
- package/plugins/lisa-devin/agents/learnings-synthesizer.md +155 -0
- package/plugins/lisa-devin/agents/linear-agent.md +138 -0
- package/plugins/lisa-devin/agents/linear-build-intake.md +64 -0
- package/plugins/lisa-devin/agents/linear-prd-intake.md +66 -0
- package/plugins/lisa-devin/agents/notion-prd-intake.md +63 -0
- package/plugins/lisa-devin/agents/performance-specialist.md +26 -0
- package/plugins/lisa-devin/agents/pr-mining-specialist.md +85 -0
- package/plugins/lisa-devin/agents/product-specialist.md +30 -0
- package/plugins/lisa-devin/agents/quality-specialist.md +30 -0
- package/plugins/lisa-devin/agents/security-specialist.md +43 -0
- package/plugins/lisa-devin/agents/skill-evaluator.md +205 -0
- package/plugins/lisa-devin/agents/spec-conformance-specialist.md +56 -0
- package/plugins/lisa-devin/agents/test-specialist.md +32 -0
- package/plugins/lisa-devin/agents/tracker-mining-specialist.md +85 -0
- package/plugins/lisa-devin/agents/verification-specialist.md +145 -0
- package/plugins/lisa-devin/hooks/auto-update.mjs +824 -0
- package/plugins/lisa-devin/hooks/auto-update.sh +31 -0
- package/plugins/lisa-devin/hooks/block-blind-automerge.sh +1242 -0
- package/plugins/lisa-devin/hooks/block-direct-issue-create.sh +2603 -0
- package/plugins/lisa-devin/hooks/block-host-name-leak.mjs +412 -0
- package/plugins/lisa-devin/hooks/block-host-name-leak.sh +61 -0
- package/plugins/lisa-devin/hooks/block-instruction-file-edits.sh +207 -0
- package/plugins/lisa-devin/hooks/block-managed-file-edits.sh +1175 -0
- package/plugins/lisa-devin/hooks/block-no-verify.sh +2288 -0
- package/plugins/lisa-devin/hooks/block-shell-json-parsing.sh +263 -0
- package/plugins/lisa-devin/hooks/cleanup-stale-worktrees.sh +122 -0
- package/plugins/lisa-devin/hooks/devin-tool-name-shim.sh +30 -0
- package/plugins/lisa-devin/hooks/discharge-work-item-gates.sh +90 -0
- package/plugins/lisa-devin/hooks/enforce-verification-gate.sh +506 -0
- package/plugins/lisa-devin/hooks/enforcement-vintage-npm.mjs +320 -0
- package/plugins/lisa-devin/hooks/enforcement-vintage.mjs +472 -0
- package/plugins/lisa-devin/hooks/enforcement-vintage.sh +48 -0
- package/plugins/lisa-devin/hooks/failure-signature-index.mjs +717 -0
- package/plugins/lisa-devin/hooks/failure-signature-index.sh +26 -0
- package/plugins/lisa-devin/hooks/guard-dedupe.bash +374 -0
- package/plugins/lisa-devin/hooks/inject-resolved-config.mjs +903 -0
- package/plugins/lisa-devin/hooks/inject-resolved-config.sh +107 -0
- package/plugins/lisa-devin/hooks/inject-rules.sh +49 -0
- package/plugins/lisa-devin/hooks/install-pkgs.sh +84 -0
- package/plugins/lisa-devin/hooks/operational-hazards.mjs +736 -0
- package/plugins/lisa-devin/hooks/operational-hazards.sh +28 -0
- package/plugins/lisa-devin/hooks/parity-safety-net-heredoc.py +1004 -0
- package/plugins/lisa-devin/hooks/parity-safety-net.sh +3275 -0
- package/plugins/lisa-devin/hooks/secrets-preflight.sh +72 -0
- package/plugins/lisa-devin/hooks/setup-jira-cli.sh +205 -0
- package/plugins/lisa-devin/hooks/shell-write-nudge.sh +86 -0
- package/plugins/lisa-devin/hooks/sonar-secrets.sh +205 -0
- package/plugins/lisa-devin/hooks/threshold-ratchet-compare.mjs +518 -0
- package/plugins/lisa-devin/hooks/threshold-ratchet-families.mjs +543 -0
- package/plugins/lisa-devin/hooks/threshold-ratchet.mjs +568 -0
- package/plugins/lisa-devin/hooks/threshold-ratchet.sh +22 -0
- package/plugins/lisa-devin/hooks/withdrawn-rulings.mjs +600 -0
- package/plugins/lisa-devin/hooks/withdrawn-rulings.sh +24 -0
- package/plugins/lisa-devin/hooks/worktree-binding-guard.mjs +1383 -0
- package/plugins/lisa-devin/hooks/worktree-binding-guard.sh +79 -0
- package/plugins/lisa-devin/hooks.json +247 -0
- package/plugins/lisa-devin/rules/eager/00-rule-index.md +82 -0
- package/plugins/lisa-devin/rules/eager/base-rules.md +85 -0
- package/plugins/lisa-devin/rules/eager/coding-philosophy.md +27 -0
- package/plugins/lisa-devin/rules/eager/config-resolution.md +37 -0
- package/plugins/lisa-devin/rules/eager/do-it-now.md +11 -0
- package/plugins/lisa-devin/rules/eager/empirical-inquiry.md +24 -0
- package/plugins/lisa-devin/rules/eager/falsifiable-checks.md +48 -0
- package/plugins/lisa-devin/rules/eager/history-audit.md +27 -0
- package/plugins/lisa-devin/rules/eager/integration-access-layer.md +19 -0
- package/plugins/lisa-devin/rules/eager/intent-routing.md +18 -0
- package/plugins/lisa-devin/rules/eager/learnings-ladder.md +18 -0
- package/plugins/lisa-devin/rules/eager/local-ci-first.md +15 -0
- package/plugins/lisa-devin/rules/eager/measurement-integrity.md +18 -0
- package/plugins/lisa-devin/rules/eager/never-name-a-downstream-project.md +9 -0
- package/plugins/lisa-devin/rules/eager/not-blocked-just-waiting.md +13 -0
- package/plugins/lisa-devin/rules/eager/operational-hazards.md +50 -0
- package/plugins/lisa-devin/rules/eager/report-actionability.md +26 -0
- package/plugins/lisa-devin/rules/eager/security-audit-handling.md +40 -0
- package/plugins/lisa-devin/rules/eager/session-status-updates.md +20 -0
- package/plugins/lisa-devin/rules/eager/settled-decisions.md +75 -0
- package/plugins/lisa-devin/rules/eager/stale-state-claims.md +26 -0
- package/plugins/lisa-devin/rules/eager/tool-access-gate.md +23 -0
- package/plugins/lisa-devin/rules/eager/tracked-work.md +9 -0
- package/plugins/lisa-devin/rules/eager/upstream-to-lisa.md +14 -0
- package/plugins/lisa-devin/rules/eager/verification.md +33 -0
- package/plugins/lisa-devin/rules/eager/wiki-knowledge-source.md +13 -0
- package/plugins/lisa-devin/rules/eager/withdrawn-rulings.md +102 -0
- package/plugins/lisa-devin/rules/reference/automation-runbook-contract.md +355 -0
- package/plugins/lisa-devin/rules/reference/base-rules.md +136 -0
- package/plugins/lisa-devin/rules/reference/bdd-e2e-coverage.md +301 -0
- package/plugins/lisa-devin/rules/reference/blocker-containment.md +165 -0
- package/plugins/lisa-devin/rules/reference/claim-archaeology.md +184 -0
- package/plugins/lisa-devin/rules/reference/claim-evidence-mapping.md +362 -0
- package/plugins/lisa-devin/rules/reference/claim-time-guards.md +135 -0
- package/plugins/lisa-devin/rules/reference/coding-philosophy.md +428 -0
- package/plugins/lisa-devin/rules/reference/config-resolution.md +1225 -0
- package/plugins/lisa-devin/rules/reference/control-reachability.md +166 -0
- package/plugins/lisa-devin/rules/reference/convergent-review.md +145 -0
- package/plugins/lisa-devin/rules/reference/credential-substrate-precedence.md +249 -0
- package/plugins/lisa-devin/rules/reference/dependency-decision-records.md +177 -0
- package/plugins/lisa-devin/rules/reference/dependency-internalization-kit.md +244 -0
- package/plugins/lisa-devin/rules/reference/dependency-trust-classes.md +291 -0
- package/plugins/lisa-devin/rules/reference/deployed-state-readback.md +142 -0
- package/plugins/lisa-devin/rules/reference/derived-branch-plan.md +214 -0
- package/plugins/lisa-devin/rules/reference/design-source-of-truth.md +260 -0
- package/plugins/lisa-devin/rules/reference/design-value-binding.md +311 -0
- package/plugins/lisa-devin/rules/reference/do-it-now.md +19 -0
- package/plugins/lisa-devin/rules/reference/documentation-source-paths.md +31 -0
- package/plugins/lisa-devin/rules/reference/empirical-inquiry.md +28 -0
- package/plugins/lisa-devin/rules/reference/factory-model.md +111 -0
- package/plugins/lisa-devin/rules/reference/falsifiable-checks.md +275 -0
- package/plugins/lisa-devin/rules/reference/history-audit.md +42 -0
- package/plugins/lisa-devin/rules/reference/integration-access-layer.md +89 -0
- package/plugins/lisa-devin/rules/reference/intent-routing.md +428 -0
- package/plugins/lisa-devin/rules/reference/leaf-only-lifecycle.md +227 -0
- package/plugins/lisa-devin/rules/reference/learnings-ladder.md +41 -0
- package/plugins/lisa-devin/rules/reference/local-ci-first.md +34 -0
- package/plugins/lisa-devin/rules/reference/measurement-integrity.md +119 -0
- package/plugins/lisa-devin/rules/reference/never-name-a-downstream-project.md +37 -0
- package/plugins/lisa-devin/rules/reference/not-blocked-just-waiting.md +41 -0
- package/plugins/lisa-devin/rules/reference/observability-audit.md +146 -0
- package/plugins/lisa-devin/rules/reference/operational-hazards.md +115 -0
- package/plugins/lisa-devin/rules/reference/prd-definition-of-ready.md +118 -0
- package/plugins/lisa-devin/rules/reference/prd-lifecycle-rollup.md +192 -0
- package/plugins/lisa-devin/rules/reference/pre-flight-autofill.md +250 -0
- package/plugins/lisa-devin/rules/reference/project-learnings.md +159 -0
- package/plugins/lisa-devin/rules/reference/promotion-contract.md +148 -0
- package/plugins/lisa-devin/rules/reference/readiness-rubric.md +242 -0
- package/plugins/lisa-devin/rules/reference/ready-role-filing.md +212 -0
- package/plugins/lisa-devin/rules/reference/rejection-detection.md +308 -0
- package/plugins/lisa-devin/rules/reference/repo-scope-split.md +119 -0
- package/plugins/lisa-devin/rules/reference/report-actionability.md +61 -0
- package/plugins/lisa-devin/rules/reference/reset-seed-coverage.md +286 -0
- package/plugins/lisa-devin/rules/reference/security-audit-handling.md +55 -0
- package/plugins/lisa-devin/rules/reference/session-status-updates.md +111 -0
- package/plugins/lisa-devin/rules/reference/settled-decisions.md +39 -0
- package/plugins/lisa-devin/rules/reference/stale-state-claims.md +88 -0
- package/plugins/lisa-devin/rules/reference/tool-access-gate.md +114 -0
- package/plugins/lisa-devin/rules/reference/tracked-work.md +49 -0
- package/plugins/lisa-devin/rules/reference/upstream-to-lisa.md +26 -0
- package/plugins/lisa-devin/rules/reference/usage-accounting.md +261 -0
- package/plugins/lisa-devin/rules/reference/verification.md +278 -0
- package/plugins/lisa-devin/rules/reference/wiki-knowledge-source.md +37 -0
- package/plugins/lisa-devin/rules/reference/withdrawn-rulings.md +148 -0
- package/plugins/lisa-devin/rules/reference/work-item-definition-of-ready.md +177 -0
- package/plugins/lisa-devin/rules/reference/work-item-trailer-definition.md +129 -0
- package/plugins/lisa-devin/scripts/automation-run-record.mjs +678 -0
- package/plugins/lisa-devin/scripts/automation-status-claude-adapter.mjs +804 -0
- package/plugins/lisa-devin/scripts/automation-status-codex-adapter.mjs +1081 -0
- package/plugins/lisa-devin/scripts/automation-status-contract-drift.mjs +392 -0
- package/plugins/lisa-devin/scripts/automation-status-expected-fleet.mjs +508 -0
- package/plugins/lisa-devin/scripts/automation-status-report.mjs +200 -0
- package/plugins/lisa-devin/scripts/automation-status-run-history.mjs +216 -0
- package/plugins/lisa-devin/scripts/automation-status-unrecorded-runs.mjs +127 -0
- package/plugins/lisa-devin/scripts/blocker-edge-resolution.mjs +150 -0
- package/plugins/lisa-devin/scripts/cross-pollinate.mjs +763 -0
- package/plugins/lisa-devin/scripts/design-bindings-probe.mjs +713 -0
- package/plugins/lisa-devin/scripts/design-intake-gate.mjs +470 -0
- package/plugins/lisa-devin/scripts/design-source-gate.mjs +610 -0
- package/plugins/lisa-devin/scripts/design-variable-ids.mjs +567 -0
- package/plugins/lisa-devin/scripts/doctor-report.mjs +635 -0
- package/plugins/lisa-devin/scripts/install-remote-agent-aws.mjs +443 -0
- package/plugins/lisa-devin/scripts/intake-blocker-reprobe.mjs +1065 -0
- package/plugins/lisa-devin/scripts/intake-prework-denominator.mjs +249 -0
- package/plugins/lisa-devin/scripts/lifecycle-label-trust.mjs +593 -0
- package/plugins/lisa-devin/scripts/linear-state-write-target.mjs +362 -0
- package/plugins/lisa-devin/scripts/plugin-sync-explain.mjs +654 -0
- package/plugins/lisa-devin/scripts/pr-arming-sweep.mjs +561 -0
- package/plugins/lisa-devin/scripts/project-ideation-idempotency-harness.mjs +338 -0
- package/plugins/lisa-devin/scripts/qa-signal-lifecycle.mjs +523 -0
- package/plugins/lisa-devin/scripts/queue-contract-resolution.mjs +583 -0
- package/plugins/lisa-devin/scripts/queue-health-classification.mjs +157 -0
- package/plugins/lisa-devin/scripts/queue-status-build-readers.mjs +561 -0
- package/plugins/lisa-devin/scripts/queue-status-prd-readers.mjs +452 -0
- package/plugins/lisa-devin/scripts/remote-agent-aws-setup.sh +677 -0
- package/plugins/lisa-devin/scripts/repo-scope-vocabulary-audit.mjs +458 -0
- package/plugins/lisa-devin/scripts/resolve-lifecycle-role.mjs +347 -0
- package/plugins/lisa-devin/scripts/rollup-blocker-classification.mjs +616 -0
- package/plugins/lisa-devin/scripts/scoping-label-audit.mjs +474 -0
- package/plugins/lisa-devin/skills/lisa-acceptance-criteria/SKILL.md +73 -0
- package/plugins/lisa-devin/skills/lisa-agent-design-best-practices/SKILL.md +242 -0
- package/plugins/lisa-devin/skills/lisa-agent-ready/SKILL.md +271 -0
- package/plugins/lisa-devin/skills/lisa-analyze-claude-remote/SKILL.md +434 -0
- package/plugins/lisa-devin/skills/lisa-atlassian-access/SKILL.md +469 -0
- package/plugins/lisa-devin/skills/lisa-atlassian-access/scripts/markdown-to-adf.mjs +236 -0
- package/plugins/lisa-devin/skills/lisa-attribute-failure/SKILL.md +142 -0
- package/plugins/lisa-devin/skills/lisa-automation-status/SKILL.md +149 -0
- package/plugins/lisa-devin/skills/lisa-bug-triage/SKILL.md +23 -0
- package/plugins/lisa-devin/skills/lisa-capability-drift/SKILL.md +71 -0
- package/plugins/lisa-devin/skills/lisa-codebase-research/SKILL.md +87 -0
- package/plugins/lisa-devin/skills/lisa-codify-verification/SKILL.md +213 -0
- package/plugins/lisa-devin/skills/lisa-confluence-prd-intake/SKILL.md +417 -0
- package/plugins/lisa-devin/skills/lisa-confluence-to-tracker/SKILL.md +469 -0
- package/plugins/lisa-devin/skills/lisa-confluence-write-prd/SKILL.md +111 -0
- package/plugins/lisa-devin/skills/lisa-cross-pollinate/SKILL.md +175 -0
- package/plugins/lisa-devin/skills/lisa-debrief/SKILL.md +96 -0
- package/plugins/lisa-devin/skills/lisa-debrief-apply/SKILL.md +106 -0
- package/plugins/lisa-devin/skills/lisa-delivery-effectiveness/SKILL.md +62 -0
- package/plugins/lisa-devin/skills/lisa-design-intake/SKILL.md +198 -0
- package/plugins/lisa-devin/skills/lisa-detect-tooling/SKILL.md +110 -0
- package/plugins/lisa-devin/skills/lisa-detect-tooling/scripts/commands.mjs +479 -0
- package/plugins/lisa-devin/skills/lisa-detect-tooling/scripts/detect-tooling.mjs +658 -0
- package/plugins/lisa-devin/skills/lisa-doctor/SKILL.md +743 -0
- package/plugins/lisa-devin/skills/lisa-drive-pr-to-merge/SKILL.md +1587 -0
- package/plugins/lisa-devin/skills/lisa-epic-triage/SKILL.md +28 -0
- package/plugins/lisa-devin/skills/lisa-evaluation-suite/SKILL.md +63 -0
- package/plugins/lisa-devin/skills/lisa-exploratory-qa/SKILL.md +185 -0
- package/plugins/lisa-devin/skills/lisa-fix-linter-error/SKILL.md +45 -0
- package/plugins/lisa-devin/skills/lisa-generate-claude-remote-build-script/SKILL.md +235 -0
- package/plugins/lisa-devin/skills/lisa-git-commit/SKILL.md +53 -0
- package/plugins/lisa-devin/skills/lisa-git-prune/SKILL.md +35 -0
- package/plugins/lisa-devin/skills/lisa-git-submit-pr/SKILL.md +170 -0
- package/plugins/lisa-devin/skills/lisa-github-add-journey/SKILL.md +118 -0
- package/plugins/lisa-devin/skills/lisa-github-build-intake/SKILL.md +745 -0
- package/plugins/lisa-devin/skills/lisa-github-claim/SKILL.md +27 -0
- package/plugins/lisa-devin/skills/lisa-github-create/SKILL.md +105 -0
- package/plugins/lisa-devin/skills/lisa-github-evidence/SKILL.md +120 -0
- package/plugins/lisa-devin/skills/lisa-github-journey/SKILL.md +134 -0
- package/plugins/lisa-devin/skills/lisa-github-prd-intake/SKILL.md +424 -0
- package/plugins/lisa-devin/skills/lisa-github-project-v2/SKILL.md +227 -0
- package/plugins/lisa-devin/skills/lisa-github-read-issue/SKILL.md +305 -0
- package/plugins/lisa-devin/skills/lisa-github-sync/SKILL.md +201 -0
- package/plugins/lisa-devin/skills/lisa-github-to-tracker/SKILL.md +456 -0
- package/plugins/lisa-devin/skills/lisa-github-validate-issue/SKILL.md +598 -0
- package/plugins/lisa-devin/skills/lisa-github-verify/SKILL.md +60 -0
- package/plugins/lisa-devin/skills/lisa-github-write-issue/SKILL.md +531 -0
- package/plugins/lisa-devin/skills/lisa-github-write-prd/SKILL.md +156 -0
- package/plugins/lisa-devin/skills/lisa-health/SKILL.md +142 -0
- package/plugins/lisa-devin/skills/lisa-health-drift-cron/SKILL.md +80 -0
- package/plugins/lisa-devin/skills/lisa-implement/SKILL.md +372 -0
- package/plugins/lisa-devin/skills/lisa-improve-code-complexity/SKILL.md +44 -0
- package/plugins/lisa-devin/skills/lisa-improve-harness/SKILL.md +487 -0
- package/plugins/lisa-devin/skills/lisa-improve-max-lines/SKILL.md +45 -0
- package/plugins/lisa-devin/skills/lisa-improve-max-lines-per-function/SKILL.md +46 -0
- package/plugins/lisa-devin/skills/lisa-improve-test-coverage/SKILL.md +47 -0
- package/plugins/lisa-devin/skills/lisa-improve-tests/SKILL.md +50 -0
- package/plugins/lisa-devin/skills/lisa-intake/SKILL.md +208 -0
- package/plugins/lisa-devin/skills/lisa-intake-explain/SKILL.md +279 -0
- package/plugins/lisa-devin/skills/lisa-jam-access/SKILL.md +128 -0
- package/plugins/lisa-devin/skills/lisa-jira-add-journey/SKILL.md +139 -0
- package/plugins/lisa-devin/skills/lisa-jira-build-intake/SKILL.md +556 -0
- package/plugins/lisa-devin/skills/lisa-jira-claim/SKILL.md +27 -0
- package/plugins/lisa-devin/skills/lisa-jira-create/SKILL.md +157 -0
- package/plugins/lisa-devin/skills/lisa-jira-evidence/SKILL.md +106 -0
- package/plugins/lisa-devin/skills/lisa-jira-evidence/scripts/post-evidence.sh +262 -0
- package/plugins/lisa-devin/skills/lisa-jira-journey/SKILL.md +168 -0
- package/plugins/lisa-devin/skills/lisa-jira-journey/scripts/generate-templates.py +239 -0
- package/plugins/lisa-devin/skills/lisa-jira-journey/scripts/parse-plan.py +570 -0
- package/plugins/lisa-devin/skills/lisa-jira-read-ticket/SKILL.md +199 -0
- package/plugins/lisa-devin/skills/lisa-jira-read-ticket/scripts/download-attachment.sh +211 -0
- package/plugins/lisa-devin/skills/lisa-jira-sync/SKILL.md +117 -0
- package/plugins/lisa-devin/skills/lisa-jira-validate-ticket/SKILL.md +525 -0
- package/plugins/lisa-devin/skills/lisa-jira-verify/SKILL.md +61 -0
- package/plugins/lisa-devin/skills/lisa-jira-write-ticket/SKILL.md +440 -0
- package/plugins/lisa-devin/skills/lisa-jsdoc-best-practices/SKILL.md +491 -0
- package/plugins/lisa-devin/skills/lisa-kane-browser/SKILL.md +80 -0
- package/plugins/lisa-devin/skills/lisa-learnings-audit/SKILL.md +490 -0
- package/plugins/lisa-devin/skills/lisa-linear-access/SKILL.md +483 -0
- package/plugins/lisa-devin/skills/lisa-linear-add-journey/SKILL.md +109 -0
- package/plugins/lisa-devin/skills/lisa-linear-build-intake/SKILL.md +548 -0
- package/plugins/lisa-devin/skills/lisa-linear-claim/SKILL.md +28 -0
- package/plugins/lisa-devin/skills/lisa-linear-create/SKILL.md +150 -0
- package/plugins/lisa-devin/skills/lisa-linear-evidence/SKILL.md +124 -0
- package/plugins/lisa-devin/skills/lisa-linear-journey/SKILL.md +147 -0
- package/plugins/lisa-devin/skills/lisa-linear-prd-intake/SKILL.md +411 -0
- package/plugins/lisa-devin/skills/lisa-linear-read-issue/SKILL.md +201 -0
- package/plugins/lisa-devin/skills/lisa-linear-sync/SKILL.md +164 -0
- package/plugins/lisa-devin/skills/lisa-linear-to-tracker/SKILL.md +454 -0
- package/plugins/lisa-devin/skills/lisa-linear-validate-issue/SKILL.md +504 -0
- package/plugins/lisa-devin/skills/lisa-linear-verify/SKILL.md +65 -0
- package/plugins/lisa-devin/skills/lisa-linear-write-issue/SKILL.md +448 -0
- package/plugins/lisa-devin/skills/lisa-linear-write-prd/SKILL.md +98 -0
- package/plugins/lisa-devin/skills/lisa-monitor/SKILL.md +224 -0
- package/plugins/lisa-devin/skills/lisa-nightly-add-test-coverage/SKILL.md +40 -0
- package/plugins/lisa-devin/skills/lisa-nightly-improve-tests/SKILL.md +29 -0
- package/plugins/lisa-devin/skills/lisa-nightly-lower-code-complexity/SKILL.md +42 -0
- package/plugins/lisa-devin/skills/lisa-notion-access/SKILL.md +301 -0
- package/plugins/lisa-devin/skills/lisa-notion-prd-intake/SKILL.md +360 -0
- package/plugins/lisa-devin/skills/lisa-notion-to-tracker/SKILL.md +467 -0
- package/plugins/lisa-devin/skills/lisa-notion-write-prd/SKILL.md +111 -0
- package/plugins/lisa-devin/skills/lisa-parity-code-review/SKILL.md +83 -0
- package/plugins/lisa-devin/skills/lisa-parity-code-simplifier/SKILL.md +76 -0
- package/plugins/lisa-devin/skills/lisa-parity-coderabbit/SKILL.md +87 -0
- package/plugins/lisa-devin/skills/lisa-parity-sentry-sdk-setup/SKILL.md +375 -0
- package/plugins/lisa-devin/skills/lisa-parity-sentry-seer/SKILL.md +168 -0
- package/plugins/lisa-devin/skills/lisa-parity-skill-creator/SKILL.md +155 -0
- package/plugins/lisa-devin/skills/lisa-performance-review/SKILL.md +94 -0
- package/plugins/lisa-devin/skills/lisa-persist-learning/SKILL.md +247 -0
- package/plugins/lisa-devin/skills/lisa-plan/SKILL.md +64 -0
- package/plugins/lisa-devin/skills/lisa-plugin-sync-explain/SKILL.md +53 -0
- package/plugins/lisa-devin/skills/lisa-posthog-access/SKILL.md +140 -0
- package/plugins/lisa-devin/skills/lisa-prd-backlink/SKILL.md +274 -0
- package/plugins/lisa-devin/skills/lisa-prd-source-write/SKILL.md +104 -0
- package/plugins/lisa-devin/skills/lisa-prd-ticket-coverage/SKILL.md +187 -0
- package/plugins/lisa-devin/skills/lisa-product-walkthrough/SKILL.md +106 -0
- package/plugins/lisa-devin/skills/lisa-project-ideation/SKILL.md +417 -0
- package/plugins/lisa-devin/skills/lisa-project-ideation/examples/evidence-card-format.md +21 -0
- package/plugins/lisa-devin/skills/lisa-project-ideation/examples/host-project-only.md +22 -0
- package/plugins/lisa-devin/skills/lisa-project-ideation/examples/idempotency-verification-harness.md +57 -0
- package/plugins/lisa-devin/skills/lisa-project-ideation/examples/public-external-inspiration.md +22 -0
- package/plugins/lisa-devin/skills/lisa-project-ideation/examples/unavailable-data-rejection.md +22 -0
- package/plugins/lisa-devin/skills/lisa-pull-request-review/SKILL.md +132 -0
- package/plugins/lisa-devin/skills/lisa-quality-review/SKILL.md +63 -0
- package/plugins/lisa-devin/skills/lisa-queue-status/SKILL.md +215 -0
- package/plugins/lisa-devin/skills/lisa-remote-dispatch/SKILL.md +109 -0
- package/plugins/lisa-devin/skills/lisa-remote-dispatch/scripts/dispatch.mjs +535 -0
- package/plugins/lisa-devin/skills/lisa-repair-intake/SKILL.md +1621 -0
- package/plugins/lisa-devin/skills/lisa-reproduce-bug/SKILL.md +75 -0
- package/plugins/lisa-devin/skills/lisa-research/SKILL.md +92 -0
- package/plugins/lisa-devin/skills/lisa-review-implementation/SKILL.md +209 -0
- package/plugins/lisa-devin/skills/lisa-review-local/SKILL.md +141 -0
- package/plugins/lisa-devin/skills/lisa-rework-triage/SKILL.md +206 -0
- package/plugins/lisa-devin/skills/lisa-root-cause-analysis/SKILL.md +135 -0
- package/plugins/lisa-devin/skills/lisa-secrets-access/SKILL.md +430 -0
- package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/aws-bootstrap.mjs +433 -0
- package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/bootstrap-store.mjs +288 -0
- package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/doctor-secrets.mjs +273 -0
- package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/envfile.mjs +80 -0
- package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/inspect-vault.mjs +142 -0
- package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +1085 -0
- package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/note-format.mjs +179 -0
- package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/owner.mjs +96 -0
- package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/preflight-secrets.mjs +342 -0
- package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/prompt-secret.mjs +79 -0
- package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/providers.mjs +805 -0
- package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/publish-aws-bootstrap.mjs +680 -0
- package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/read-secret-note.mjs +105 -0
- package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/resolve-expo-token.mjs +90 -0
- package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/resolve-secret.mjs +285 -0
- package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/rotate-secret.mjs +297 -0
- package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/routing-floor.mjs +153 -0
- package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/surfaces.mjs +480 -0
- package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/sync-secret-to-ci.mjs +510 -0
- package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/tools-from-notes.mjs +63 -0
- package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/validate-config.mjs +550 -0
- package/plugins/lisa-devin/skills/lisa-security-review/SKILL.md +124 -0
- package/plugins/lisa-devin/skills/lisa-security-zap-scan/SKILL.md +53 -0
- package/plugins/lisa-devin/skills/lisa-sentry-access/SKILL.md +140 -0
- package/plugins/lisa-devin/skills/lisa-setup-atlassian/SKILL.md +407 -0
- package/plugins/lisa-devin/skills/lisa-setup-automations/SKILL.md +430 -0
- package/plugins/lisa-devin/skills/lisa-setup-automations/scripts/generate-workflow.mjs +288 -0
- package/plugins/lisa-devin/skills/lisa-setup-confluence/SKILL.md +254 -0
- package/plugins/lisa-devin/skills/lisa-setup-github/SKILL.md +319 -0
- package/plugins/lisa-devin/skills/lisa-setup-github-repo/SKILL.md +128 -0
- package/plugins/lisa-devin/skills/lisa-setup-jira/SKILL.md +198 -0
- package/plugins/lisa-devin/skills/lisa-setup-kane/SKILL.md +96 -0
- package/plugins/lisa-devin/skills/lisa-setup-linear/SKILL.md +375 -0
- package/plugins/lisa-devin/skills/lisa-setup-local-env/SKILL.md +95 -0
- package/plugins/lisa-devin/skills/lisa-setup-local-env/scripts/local-env.mjs +196 -0
- package/plugins/lisa-devin/skills/lisa-setup-notion/SKILL.md +376 -0
- package/plugins/lisa-devin/skills/lisa-setup-remote-aws/SKILL.md +149 -0
- package/plugins/lisa-devin/skills/lisa-setup-remote-env/SKILL.md +382 -0
- package/plugins/lisa-devin/skills/lisa-setup-remote-env/assets/materialized-env-authority.mjs +262 -0
- package/plugins/lisa-devin/skills/lisa-setup-remote-env/assets/session-start.sh +87 -0
- package/plugins/lisa-devin/skills/lisa-setup-remote-env/assets/setup.sh +216 -0
- package/plugins/lisa-devin/skills/lisa-setup-remote-env/scripts/environment.mjs +227 -0
- package/plugins/lisa-devin/skills/lisa-setup-remote-env/scripts/preflight-tools.mjs +378 -0
- package/plugins/lisa-devin/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +1632 -0
- package/plugins/lisa-devin/skills/lisa-setup-remote-env/scripts/tool-floor.mjs +94 -0
- package/plugins/lisa-devin/skills/lisa-setup-remote-env/scripts/toolchain.mjs +448 -0
- package/plugins/lisa-devin/skills/lisa-setup-remote-env/scripts/verify-remote-env.mjs +250 -0
- package/plugins/lisa-devin/skills/lisa-setup-sonar/SKILL.md +153 -0
- package/plugins/lisa-devin/skills/lisa-setup-workstation/SKILL.md +143 -0
- package/plugins/lisa-devin/skills/lisa-setup-workstation/scripts/bounded-child.mjs +168 -0
- package/plugins/lisa-devin/skills/lisa-setup-workstation/scripts/catalogue.mjs +293 -0
- package/plugins/lisa-devin/skills/lisa-setup-workstation/scripts/cli.mjs +333 -0
- package/plugins/lisa-devin/skills/lisa-setup-workstation/scripts/workstation.mjs +511 -0
- package/plugins/lisa-devin/skills/lisa-sonarcloud-access/SKILL.md +202 -0
- package/plugins/lisa-devin/skills/lisa-spec-conformance/SKILL.md +205 -0
- package/plugins/lisa-devin/skills/lisa-starter-sync/SKILL.md +35 -0
- package/plugins/lisa-devin/skills/lisa-sync-down/SKILL.md +209 -0
- package/plugins/lisa-devin/skills/lisa-task-decomposition/SKILL.md +195 -0
- package/plugins/lisa-devin/skills/lisa-task-triage/SKILL.md +23 -0
- package/plugins/lisa-devin/skills/lisa-tdd-implementation/SKILL.md +91 -0
- package/plugins/lisa-devin/skills/lisa-tear-down-automations/SKILL.md +85 -0
- package/plugins/lisa-devin/skills/lisa-test-strategy/SKILL.md +66 -0
- package/plugins/lisa-devin/skills/lisa-ticket-triage/SKILL.md +214 -0
- package/plugins/lisa-devin/skills/lisa-track/SKILL.md +129 -0
- package/plugins/lisa-devin/skills/lisa-tracker-add-journey/SKILL.md +28 -0
- package/plugins/lisa-devin/skills/lisa-tracker-build-intake/SKILL.md +134 -0
- package/plugins/lisa-devin/skills/lisa-tracker-claim/SKILL.md +35 -0
- package/plugins/lisa-devin/skills/lisa-tracker-create/SKILL.md +28 -0
- package/plugins/lisa-devin/skills/lisa-tracker-evidence/SKILL.md +63 -0
- package/plugins/lisa-devin/skills/lisa-tracker-journey/SKILL.md +27 -0
- package/plugins/lisa-devin/skills/lisa-tracker-read/SKILL.md +28 -0
- package/plugins/lisa-devin/skills/lisa-tracker-source-artifacts/SKILL.md +111 -0
- package/plugins/lisa-devin/skills/lisa-tracker-sync/SKILL.md +150 -0
- package/plugins/lisa-devin/skills/lisa-tracker-validate/SKILL.md +37 -0
- package/plugins/lisa-devin/skills/lisa-tracker-verify/SKILL.md +29 -0
- package/plugins/lisa-devin/skills/lisa-tracker-write/SKILL.md +55 -0
- package/plugins/lisa-devin/skills/lisa-usage-accounting/SKILL.md +205 -0
- package/plugins/lisa-devin/skills/lisa-usage-accounting/references/effectiveness.md +63 -0
- package/plugins/lisa-devin/skills/lisa-use-the-product/SKILL.md +86 -0
- package/plugins/lisa-devin/skills/lisa-validate-tracker-mapping/SKILL.md +467 -0
- package/plugins/lisa-devin/skills/lisa-verification-lifecycle/SKILL.md +384 -0
- package/plugins/lisa-devin/skills/lisa-verify/SKILL.md +55 -0
- package/plugins/lisa-devin/skills/lisa-verify-prd/SKILL.md +394 -0
- package/plugins/lisa-devin/skills/lisa-verify-workflow-change/SKILL.md +154 -0
- package/plugins/lisa-devin/skills/lisa-wiki-install/SKILL.md +101 -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-expo-devin/.claude-plugin/plugin.json +11 -0
- package/plugins/lisa-expo-devin/.devin-plugin/plugin.json +8 -0
- package/plugins/lisa-expo-devin/.mcp.json +8 -0
- package/plugins/lisa-expo-devin/THIRD-PARTY-NOTICES.md +84 -0
- package/plugins/lisa-expo-devin/agents/ops-specialist.md +124 -0
- package/plugins/lisa-expo-devin/hooks/devin-tool-name-shim.sh +30 -0
- package/plugins/lisa-expo-devin/hooks/register-maestro-mcp.sh +84 -0
- package/plugins/lisa-expo-devin/hooks.json +14 -0
- package/plugins/lisa-expo-devin/skills/add-app-clip/SKILL.md +280 -0
- package/plugins/lisa-expo-devin/skills/add-app-clip/references/native-module.md +96 -0
- package/plugins/lisa-expo-devin/skills/apollo-client/SKILL.md +238 -0
- package/plugins/lisa-expo-devin/skills/apollo-client/references/mutation-patterns.md +360 -0
- package/plugins/lisa-expo-devin/skills/atomic-design-gluestack/SKILL.md +369 -0
- package/plugins/lisa-expo-devin/skills/atomic-design-gluestack/references/atomic-levels.md +417 -0
- package/plugins/lisa-expo-devin/skills/atomic-design-gluestack/references/folder-structure.md +257 -0
- package/plugins/lisa-expo-devin/skills/atomic-design-gluestack/references/gluestack-mapping.md +233 -0
- package/plugins/lisa-expo-devin/skills/atomic-design-gluestack/scripts/test_validate_atomic_structure.py +240 -0
- package/plugins/lisa-expo-devin/skills/atomic-design-gluestack/scripts/validate_atomic_structure.py +438 -0
- package/plugins/lisa-expo-devin/skills/building-native-ui/SKILL.md +321 -0
- package/plugins/lisa-expo-devin/skills/building-native-ui/references/animations.md +220 -0
- package/plugins/lisa-expo-devin/skills/building-native-ui/references/controls.md +272 -0
- package/plugins/lisa-expo-devin/skills/building-native-ui/references/form-sheet.md +253 -0
- package/plugins/lisa-expo-devin/skills/building-native-ui/references/gradients.md +106 -0
- package/plugins/lisa-expo-devin/skills/building-native-ui/references/icons.md +213 -0
- package/plugins/lisa-expo-devin/skills/building-native-ui/references/media.md +198 -0
- package/plugins/lisa-expo-devin/skills/building-native-ui/references/route-structure.md +229 -0
- package/plugins/lisa-expo-devin/skills/building-native-ui/references/search.md +248 -0
- package/plugins/lisa-expo-devin/skills/building-native-ui/references/storage.md +121 -0
- package/plugins/lisa-expo-devin/skills/building-native-ui/references/tabs.md +433 -0
- package/plugins/lisa-expo-devin/skills/building-native-ui/references/toolbar-and-headers.md +284 -0
- package/plugins/lisa-expo-devin/skills/building-native-ui/references/visual-effects.md +197 -0
- package/plugins/lisa-expo-devin/skills/building-native-ui/references/webgpu-three.md +605 -0
- package/plugins/lisa-expo-devin/skills/building-native-ui/references/zoom-transitions.md +158 -0
- package/plugins/lisa-expo-devin/skills/container-view-pattern/SKILL.md +355 -0
- package/plugins/lisa-expo-devin/skills/container-view-pattern/references/examples.md +749 -0
- package/plugins/lisa-expo-devin/skills/container-view-pattern/references/patterns.md +318 -0
- package/plugins/lisa-expo-devin/skills/container-view-pattern/scripts/create_component.py +200 -0
- package/plugins/lisa-expo-devin/skills/container-view-pattern/scripts/validate_component.py +332 -0
- package/plugins/lisa-expo-devin/skills/cross-platform-compatibility/SKILL.md +268 -0
- package/plugins/lisa-expo-devin/skills/cross-platform-compatibility/references/common-issues.md +619 -0
- package/plugins/lisa-expo-devin/skills/cross-platform-compatibility/references/file-extensions.md +340 -0
- package/plugins/lisa-expo-devin/skills/cross-platform-compatibility/references/platform-api.md +276 -0
- package/plugins/lisa-expo-devin/skills/cross-platform-compatibility/scripts/validate_cross_platform.py +416 -0
- package/plugins/lisa-expo-devin/skills/directory-structure/SKILL.md +214 -0
- package/plugins/lisa-expo-devin/skills/directory-structure/scripts/validate_structure.py +454 -0
- package/plugins/lisa-expo-devin/skills/e2e-coverage-gaps/SKILL.md +117 -0
- package/plugins/lisa-expo-devin/skills/eas-update-insights/SKILL.md +228 -0
- package/plugins/lisa-expo-devin/skills/eas-update-insights/references/channel-insights-schema.md +47 -0
- package/plugins/lisa-expo-devin/skills/eas-update-insights/references/update-insights-schema.md +69 -0
- package/plugins/lisa-expo-devin/skills/expo-api-routes/SKILL.md +369 -0
- package/plugins/lisa-expo-devin/skills/expo-brownfield/SKILL.md +54 -0
- package/plugins/lisa-expo-devin/skills/expo-brownfield/references/brownfield-integrated.md +526 -0
- package/plugins/lisa-expo-devin/skills/expo-brownfield/references/brownfield-isolated.md +402 -0
- package/plugins/lisa-expo-devin/skills/expo-brownfield/references/comparison.md +63 -0
- package/plugins/lisa-expo-devin/skills/expo-brownfield/references/troubleshooting.md +88 -0
- package/plugins/lisa-expo-devin/skills/expo-cicd-workflows/SKILL.md +92 -0
- package/plugins/lisa-expo-devin/skills/expo-cicd-workflows/scripts/fetch.js +113 -0
- package/plugins/lisa-expo-devin/skills/expo-cicd-workflows/scripts/package.json +11 -0
- package/plugins/lisa-expo-devin/skills/expo-cicd-workflows/scripts/validate.js +85 -0
- package/plugins/lisa-expo-devin/skills/expo-deployment/SKILL.md +193 -0
- package/plugins/lisa-expo-devin/skills/expo-deployment/references/app-store-metadata.md +479 -0
- package/plugins/lisa-expo-devin/skills/expo-deployment/references/ios-app-store.md +355 -0
- package/plugins/lisa-expo-devin/skills/expo-deployment/references/play-store.md +264 -0
- package/plugins/lisa-expo-devin/skills/expo-deployment/references/testflight.md +58 -0
- package/plugins/lisa-expo-devin/skills/expo-deployment/references/workflows.md +200 -0
- package/plugins/lisa-expo-devin/skills/expo-dev-client/SKILL.md +164 -0
- package/plugins/lisa-expo-devin/skills/expo-env-config/SKILL.md +309 -0
- package/plugins/lisa-expo-devin/skills/expo-env-config/references/validation-patterns.md +417 -0
- package/plugins/lisa-expo-devin/skills/expo-module/SKILL.md +141 -0
- package/plugins/lisa-expo-devin/skills/expo-module/references/config-plugin.md +90 -0
- package/plugins/lisa-expo-devin/skills/expo-module/references/create-expo-module.md +206 -0
- package/plugins/lisa-expo-devin/skills/expo-module/references/lifecycle.md +127 -0
- package/plugins/lisa-expo-devin/skills/expo-module/references/module-config.md +48 -0
- package/plugins/lisa-expo-devin/skills/expo-module/references/native-module.md +286 -0
- package/plugins/lisa-expo-devin/skills/expo-module/references/native-view.md +171 -0
- package/plugins/lisa-expo-devin/skills/expo-router-best-practices/SKILL.md +432 -0
- package/plugins/lisa-expo-devin/skills/expo-router-best-practices/references/official-docs.md +290 -0
- package/plugins/lisa-expo-devin/skills/expo-router-best-practices/references/static-export-verification.md +54 -0
- package/plugins/lisa-expo-devin/skills/expo-router-best-practices/scripts/generate-route.py +171 -0
- package/plugins/lisa-expo-devin/skills/expo-tailwind-setup/SKILL.md +487 -0
- package/plugins/lisa-expo-devin/skills/expo-ui-jetpack-compose/SKILL.md +40 -0
- package/plugins/lisa-expo-devin/skills/expo-ui-swift-ui/SKILL.md +39 -0
- package/plugins/lisa-expo-devin/skills/gluestack-nativewind/SKILL.md +419 -0
- package/plugins/lisa-expo-devin/skills/gluestack-nativewind/references/color-tokens.md +343 -0
- package/plugins/lisa-expo-devin/skills/gluestack-nativewind/references/component-mapping.md +307 -0
- package/plugins/lisa-expo-devin/skills/gluestack-nativewind/references/spacing-scale.md +300 -0
- package/plugins/lisa-expo-devin/skills/gluestack-nativewind/scripts/test_validate_styling.py +240 -0
- package/plugins/lisa-expo-devin/skills/gluestack-nativewind/scripts/validate_styling.py +424 -0
- package/plugins/lisa-expo-devin/skills/jira-add-journey/SKILL.md +140 -0
- package/plugins/lisa-expo-devin/skills/jira-create/SKILL.md +161 -0
- package/plugins/lisa-expo-devin/skills/jira-evidence/SKILL.md +84 -0
- package/plugins/lisa-expo-devin/skills/jira-evidence/scripts/post-evidence.sh +262 -0
- package/plugins/lisa-expo-devin/skills/jira-journey/SKILL.md +196 -0
- package/plugins/lisa-expo-devin/skills/jira-journey/scripts/generate-templates.py +281 -0
- package/plugins/lisa-expo-devin/skills/jira-journey/scripts/parse-plan.py +400 -0
- package/plugins/lisa-expo-devin/skills/jira-verify/SKILL.md +27 -0
- package/plugins/lisa-expo-devin/skills/local-state/SKILL.md +362 -0
- package/plugins/lisa-expo-devin/skills/local-state/references/async-storage.md +505 -0
- package/plugins/lisa-expo-devin/skills/local-state/references/persistence-patterns.md +711 -0
- package/plugins/lisa-expo-devin/skills/local-state/references/reactive-variables.md +446 -0
- package/plugins/lisa-expo-devin/skills/maestro-mcp-setup/SKILL.md +144 -0
- package/plugins/lisa-expo-devin/skills/native-data-fetching/SKILL.md +507 -0
- package/plugins/lisa-expo-devin/skills/native-data-fetching/references/expo-router-loaders.md +344 -0
- package/plugins/lisa-expo-devin/skills/ops-browser-uat/SKILL.md +124 -0
- package/plugins/lisa-expo-devin/skills/ops-check-logs/SKILL.md +217 -0
- package/plugins/lisa-expo-devin/skills/ops-db-ops/SKILL.md +214 -0
- package/plugins/lisa-expo-devin/skills/ops-deploy/SKILL.md +123 -0
- package/plugins/lisa-expo-devin/skills/ops-monitor-errors/SKILL.md +99 -0
- package/plugins/lisa-expo-devin/skills/ops-performance/SKILL.md +165 -0
- package/plugins/lisa-expo-devin/skills/ops-run-local/SKILL.md +169 -0
- package/plugins/lisa-expo-devin/skills/ops-verify-health/SKILL.md +101 -0
- package/plugins/lisa-expo-devin/skills/owasp-zap/SKILL.md +61 -0
- package/plugins/lisa-expo-devin/skills/play-store-access/SKILL.md +226 -0
- package/plugins/lisa-expo-devin/skills/playwright-ci-debugging/SKILL.md +140 -0
- package/plugins/lisa-expo-devin/skills/playwright-selectors/SKILL.md +496 -0
- package/plugins/lisa-expo-devin/skills/reduce-complexity/SKILL.md +251 -0
- package/plugins/lisa-expo-devin/skills/reduce-complexity/references/extraction-strategies.md +456 -0
- package/plugins/lisa-expo-devin/skills/reduce-complexity/references/refactoring-patterns.md +557 -0
- package/plugins/lisa-expo-devin/skills/testing-library/SKILL.md +314 -0
- package/plugins/lisa-expo-devin/skills/testing-library/references/async-patterns.md +420 -0
- package/plugins/lisa-expo-devin/skills/testing-library/references/expo-router-testing.md +556 -0
- package/plugins/lisa-expo-devin/skills/testing-library/references/mocking-patterns.md +612 -0
- package/plugins/lisa-expo-devin/skills/testing-library/references/query-priority.md +291 -0
- package/plugins/lisa-expo-devin/skills/upgrading-expo/SKILL.md +134 -0
- package/plugins/lisa-expo-devin/skills/upgrading-expo/references/expo-av-to-audio.md +132 -0
- package/plugins/lisa-expo-devin/skills/upgrading-expo/references/expo-av-to-video.md +160 -0
- package/plugins/lisa-expo-devin/skills/upgrading-expo/references/native-tabs.md +124 -0
- package/plugins/lisa-expo-devin/skills/upgrading-expo/references/new-architecture.md +79 -0
- package/plugins/lisa-expo-devin/skills/upgrading-expo/references/react-19.md +79 -0
- package/plugins/lisa-expo-devin/skills/upgrading-expo/references/react-compiler.md +59 -0
- package/plugins/lisa-expo-devin/skills/upgrading-expo/references/react-navigation-to-expo-router.md +61 -0
- package/plugins/lisa-expo-devin/skills/use-dom/SKILL.md +417 -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-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-harper-fabric-devin/.claude-plugin/plugin.json +11 -0
- package/plugins/lisa-harper-fabric-devin/.devin-plugin/plugin.json +8 -0
- package/plugins/lisa-harper-fabric-devin/generated-artifact-globs.txt +5 -0
- package/plugins/lisa-harper-fabric-devin/hooks/block-generated-artifact-edits.sh +141 -0
- package/plugins/lisa-harper-fabric-devin/hooks/devin-tool-name-shim.sh +30 -0
- package/plugins/lisa-harper-fabric-devin/hooks/enforce-config-extensions.mjs +196 -0
- package/plugins/lisa-harper-fabric-devin/hooks/enforce-config-extensions.sh +46 -0
- package/plugins/lisa-harper-fabric-devin/hooks/inject-rules.sh +27 -0
- package/plugins/lisa-harper-fabric-devin/hooks.json +36 -0
- package/plugins/lisa-harper-fabric-devin/rules/eager/harper-fabric.md +31 -0
- package/plugins/lisa-harper-fabric-devin/rules/reference/harper-fabric.md +52 -0
- package/plugins/lisa-harper-fabric-devin/skills/e2e-coverage-gaps/SKILL.md +117 -0
- package/plugins/lisa-harper-fabric-devin/skills/harper-auth/SKILL.md +368 -0
- package/plugins/lisa-harper-fabric-devin/skills/harper-build-and-deploy/SKILL.md +198 -0
- package/plugins/lisa-harper-fabric-devin/skills/harper-caching/SKILL.md +265 -0
- package/plugins/lisa-harper-fabric-devin/skills/harper-component-model/SKILL.md +87 -0
- package/plugins/lisa-harper-fabric-devin/skills/harper-config-yaml/SKILL.md +283 -0
- package/plugins/lisa-harper-fabric-devin/skills/harper-operations/SKILL.md +239 -0
- package/plugins/lisa-harper-fabric-devin/skills/harper-realtime/SKILL.md +187 -0
- package/plugins/lisa-harper-fabric-devin/skills/harper-resources/SKILL.md +142 -0
- package/plugins/lisa-harper-fabric-devin/skills/harper-rest-queries/SKILL.md +403 -0
- package/plugins/lisa-harper-fabric-devin/skills/harper-schema-graphql/SKILL.md +123 -0
- package/plugins/lisa-harper-fabric-devin/skills/harper-testing/SKILL.md +254 -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-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-nestjs-devin/.claude-plugin/plugin.json +11 -0
- package/plugins/lisa-nestjs-devin/.devin-plugin/plugin.json +8 -0
- package/plugins/lisa-nestjs-devin/hooks/block-migration-edits.sh +125 -0
- package/plugins/lisa-nestjs-devin/hooks/devin-tool-name-shim.sh +30 -0
- package/plugins/lisa-nestjs-devin/hooks/lisa-edit-gate.sh +152 -0
- package/plugins/lisa-nestjs-devin/hooks.json +15 -0
- package/plugins/lisa-nestjs-devin/skills/nestjs-graphql/SKILL.md +176 -0
- package/plugins/lisa-nestjs-devin/skills/nestjs-graphql/references/advanced-features.md +527 -0
- package/plugins/lisa-nestjs-devin/skills/nestjs-graphql/references/project-patterns.md +531 -0
- package/plugins/lisa-nestjs-devin/skills/nestjs-graphql/references/quick-start.md +257 -0
- package/plugins/lisa-nestjs-devin/skills/nestjs-graphql/references/resolvers-mutations.md +413 -0
- package/plugins/lisa-nestjs-devin/skills/nestjs-graphql/references/types-scalars.md +513 -0
- package/plugins/lisa-nestjs-devin/skills/nestjs-rules/SKILL.md +560 -0
- package/plugins/lisa-nestjs-devin/skills/typeorm-patterns/SKILL.md +275 -0
- package/plugins/lisa-nestjs-devin/skills/typeorm-patterns/references/configuration-patterns.md +487 -0
- package/plugins/lisa-nestjs-devin/skills/typeorm-patterns/references/entity-patterns.md +450 -0
- package/plugins/lisa-nestjs-devin/skills/typeorm-patterns/references/observability-patterns.md +536 -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-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-openclaw-devin/.claude-plugin/plugin.json +8 -0
- package/plugins/lisa-openclaw-devin/.devin-plugin/plugin.json +8 -0
- package/plugins/lisa-openclaw-devin/skills/lisa-openclaw-connect-repo-topic/SKILL.md +163 -0
- package/plugins/lisa-openclaw-devin/skills/lisa-openclaw-connect-repo-topic/references/repo-topic-config.md +185 -0
- package/plugins/lisa-openclaw-devin/skills/lisa-openclaw-connect-staff/SKILL.md +175 -0
- package/plugins/lisa-openclaw-devin/skills/lisa-openclaw-connect-staff/references/platform-routing.md +123 -0
- package/plugins/lisa-openclaw-devin/skills/lisa-openclaw-connect-staff/references/prompts.md +78 -0
- package/plugins/lisa-openclaw-devin/skills/lisa-openclaw-setup/SKILL.md +141 -0
- 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-phaser-devin/.claude-plugin/plugin.json +11 -0
- package/plugins/lisa-phaser-devin/.devin-plugin/plugin.json +8 -0
- package/plugins/lisa-phaser-devin/agents/accessibility-advocate.md +55 -0
- package/plugins/lisa-phaser-devin/agents/art-director.md +90 -0
- package/plugins/lisa-phaser-devin/agents/audio-director.md +65 -0
- package/plugins/lisa-phaser-devin/agents/combat-designer.md +61 -0
- package/plugins/lisa-phaser-devin/agents/economy-designer.md +59 -0
- package/plugins/lisa-phaser-devin/agents/game-designer.md +62 -0
- package/plugins/lisa-phaser-devin/agents/game-feel-specialist.md +56 -0
- package/plugins/lisa-phaser-devin/agents/level-designer.md +59 -0
- package/plugins/lisa-phaser-devin/agents/localization-manager.md +61 -0
- package/plugins/lisa-phaser-devin/agents/marketing-strategist.md +59 -0
- package/plugins/lisa-phaser-devin/agents/monetization-designer.md +59 -0
- package/plugins/lisa-phaser-devin/agents/narrative-designer.md +56 -0
- package/plugins/lisa-phaser-devin/agents/onboarding-advocate.md +59 -0
- package/plugins/lisa-phaser-devin/agents/player-advocate.md +57 -0
- package/plugins/lisa-phaser-devin/agents/producer.md +61 -0
- package/plugins/lisa-phaser-devin/agents/product-analyst.md +62 -0
- package/plugins/lisa-phaser-devin/agents/publisher.md +59 -0
- package/plugins/lisa-phaser-devin/agents/qa-playtester.md +57 -0
- package/plugins/lisa-phaser-devin/agents/target-player.md +52 -0
- package/plugins/lisa-phaser-devin/agents/ux-ui-designer.md +60 -0
- package/plugins/lisa-phaser-devin/hooks/devin-tool-name-shim.sh +30 -0
- package/plugins/lisa-phaser-devin/hooks/inject-rules.sh +27 -0
- package/plugins/lisa-phaser-devin/hooks.json +14 -0
- package/plugins/lisa-phaser-devin/rules/eager/phaser.md +44 -0
- package/plugins/lisa-phaser-devin/rules/reference/phaser.md +184 -0
- package/plugins/lisa-phaser-devin/skills/phaser-accessibility/SKILL.md +135 -0
- package/plugins/lisa-phaser-devin/skills/phaser-asset-pipeline/SKILL.md +222 -0
- package/plugins/lisa-phaser-devin/skills/phaser-asset-sourcing/SKILL.md +151 -0
- package/plugins/lisa-phaser-devin/skills/phaser-build-deploy/SKILL.md +153 -0
- package/plugins/lisa-phaser-devin/skills/phaser-i18n/SKILL.md +122 -0
- package/plugins/lisa-phaser-devin/skills/phaser-project-structure/SKILL.md +89 -0
- package/plugins/lisa-phaser-devin/skills/phaser-services/SKILL.md +208 -0
- package/plugins/lisa-phaser-devin/skills/phaser-testing/SKILL.md +192 -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-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-rails-devin/.claude-plugin/plugin.json +11 -0
- package/plugins/lisa-rails-devin/.devin-plugin/plugin.json +8 -0
- package/plugins/lisa-rails-devin/agents/ops-specialist.md +226 -0
- package/plugins/lisa-rails-devin/hooks/devin-tool-name-shim.sh +30 -0
- package/plugins/lisa-rails-devin/hooks/inject-rules.sh +40 -0
- package/plugins/lisa-rails-devin/hooks/lisa-edit-gate.sh +152 -0
- package/plugins/lisa-rails-devin/hooks/rubocop-on-edit.sh +101 -0
- package/plugins/lisa-rails-devin/hooks/sg-scan-on-edit.sh +97 -0
- package/plugins/lisa-rails-devin/hooks.json +29 -0
- package/plugins/lisa-rails-devin/rules/eager/rails-conventions.md +23 -0
- package/plugins/lisa-rails-devin/rules/reference/rails-conventions.md +176 -0
- package/plugins/lisa-rails-devin/skills/action-controller-best-practices/SKILL.md +374 -0
- package/plugins/lisa-rails-devin/skills/action-view-best-practices/SKILL.md +335 -0
- package/plugins/lisa-rails-devin/skills/active-record-model-best-practices/SKILL.md +166 -0
- package/plugins/lisa-rails-devin/skills/e2e-coverage-gaps/SKILL.md +117 -0
- package/plugins/lisa-rails-devin/skills/fix-linter-error/SKILL.md +45 -0
- package/plugins/lisa-rails-devin/skills/improve-code-complexity/SKILL.md +51 -0
- package/plugins/lisa-rails-devin/skills/improve-max-lines/SKILL.md +46 -0
- package/plugins/lisa-rails-devin/skills/improve-max-lines-per-function/SKILL.md +46 -0
- package/plugins/lisa-rails-devin/skills/improve-test-coverage/SKILL.md +48 -0
- package/plugins/lisa-rails-devin/skills/jira-add-journey/SKILL.md +79 -0
- package/plugins/lisa-rails-devin/skills/jira-create/SKILL.md +100 -0
- package/plugins/lisa-rails-devin/skills/jira-evidence/SKILL.md +76 -0
- package/plugins/lisa-rails-devin/skills/jira-evidence/scripts/post-evidence.sh +262 -0
- package/plugins/lisa-rails-devin/skills/jira-journey/SKILL.md +65 -0
- package/plugins/lisa-rails-devin/skills/jira-verify/SKILL.md +26 -0
- package/plugins/lisa-rails-devin/skills/ops-check-logs/SKILL.md +191 -0
- package/plugins/lisa-rails-devin/skills/ops-deploy/SKILL.md +153 -0
- package/plugins/lisa-rails-devin/skills/ops-run-local/SKILL.md +169 -0
- package/plugins/lisa-rails-devin/skills/ops-verify-jobs/SKILL.md +157 -0
- package/plugins/lisa-rails-devin/skills/ops-verify-telemetry/SKILL.md +226 -0
- 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-typescript-devin/.claude-plugin/plugin.json +11 -0
- package/plugins/lisa-typescript-devin/.devin-plugin/plugin.json +8 -0
- package/plugins/lisa-typescript-devin/hooks/block-suppress-directives.sh +141 -0
- package/plugins/lisa-typescript-devin/hooks/devin-tool-name-shim.sh +30 -0
- package/plugins/lisa-typescript-devin/hooks/format-on-edit.sh +102 -0
- package/plugins/lisa-typescript-devin/hooks/lint-on-edit.sh +117 -0
- package/plugins/lisa-typescript-devin/hooks/lisa-edit-gate.sh +152 -0
- package/plugins/lisa-typescript-devin/hooks/sg-scan-on-edit.sh +94 -0
- package/plugins/lisa-typescript-devin/hooks.json +34 -0
- 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/lisa-wiki-devin/.claude-plugin/plugin.json +8 -0
- package/plugins/lisa-wiki-devin/.devin-plugin/plugin.json +8 -0
- package/plugins/lisa-wiki-devin/ci/lisa-wiki-validate.yml +33 -0
- package/plugins/lisa-wiki-devin/schema/lisa-wiki-config.schema.json +162 -0
- package/plugins/lisa-wiki-devin/schema/wiki-structure.schema.json +51 -0
- package/plugins/lisa-wiki-devin/scripts/_wiki-lib.mjs +204 -0
- package/plugins/lisa-wiki-devin/scripts/diff-guard.mjs +117 -0
- package/plugins/lisa-wiki-devin/scripts/ensure-gitignore.mjs +131 -0
- package/plugins/lisa-wiki-devin/scripts/ensure-wiki.mjs +268 -0
- package/plugins/lisa-wiki-devin/scripts/ingest-git.mjs +198 -0
- package/plugins/lisa-wiki-devin/scripts/ingest-memory.mjs +135 -0
- package/plugins/lisa-wiki-devin/scripts/ingest-roles.mjs +95 -0
- package/plugins/lisa-wiki-devin/scripts/ingest_slack_channel.py +361 -0
- package/plugins/lisa-wiki-devin/scripts/lib/bounded-child.mjs +159 -0
- package/plugins/lisa-wiki-devin/scripts/lint-wiki.mjs +513 -0
- package/plugins/lisa-wiki-devin/scripts/mcp-doctor.mjs +72 -0
- package/plugins/lisa-wiki-devin/scripts/render-contract.mjs +107 -0
- package/plugins/lisa-wiki-devin/scripts/rewrite-refs.mjs +144 -0
- package/plugins/lisa-wiki-devin/scripts/slack_oauth_user.py +179 -0
- package/plugins/lisa-wiki-devin/scripts/validate-config.mjs +321 -0
- package/plugins/lisa-wiki-devin/scripts/verify-migration.mjs +203 -0
- package/plugins/lisa-wiki-devin/scripts/verify-wiki-safety.mjs +126 -0
- package/plugins/lisa-wiki-devin/scripts/wiki-safety.mjs +378 -0
- package/plugins/lisa-wiki-devin/scripts/wiki-status.mjs +345 -0
- package/plugins/lisa-wiki-devin/skills/lisa-wiki-add-ingest/SKILL.md +34 -0
- package/plugins/lisa-wiki-devin/skills/lisa-wiki-add-role/SKILL.md +35 -0
- package/plugins/lisa-wiki-devin/skills/lisa-wiki-connector-confluence/SKILL.md +25 -0
- package/plugins/lisa-wiki-devin/skills/lisa-wiki-connector-docs/SKILL.md +30 -0
- package/plugins/lisa-wiki-devin/skills/lisa-wiki-connector-git/SKILL.md +25 -0
- package/plugins/lisa-wiki-devin/skills/lisa-wiki-connector-jira/SKILL.md +28 -0
- package/plugins/lisa-wiki-devin/skills/lisa-wiki-connector-memory/SKILL.md +28 -0
- package/plugins/lisa-wiki-devin/skills/lisa-wiki-connector-notion/SKILL.md +25 -0
- package/plugins/lisa-wiki-devin/skills/lisa-wiki-connector-roles/SKILL.md +22 -0
- package/plugins/lisa-wiki-devin/skills/lisa-wiki-connector-slack/SKILL.md +30 -0
- package/plugins/lisa-wiki-devin/skills/lisa-wiki-connector-web/SKILL.md +23 -0
- package/plugins/lisa-wiki-devin/skills/lisa-wiki-doctor/SKILL.md +47 -0
- package/plugins/lisa-wiki-devin/skills/lisa-wiki-ingest/SKILL.md +106 -0
- package/plugins/lisa-wiki-devin/skills/lisa-wiki-lint/SKILL.md +32 -0
- package/plugins/lisa-wiki-devin/skills/lisa-wiki-migrate/SKILL.md +43 -0
- package/plugins/lisa-wiki-devin/skills/lisa-wiki-onboard-me/SKILL.md +33 -0
- package/plugins/lisa-wiki-devin/skills/lisa-wiki-query/SKILL.md +40 -0
- package/plugins/lisa-wiki-devin/skills/lisa-wiki-setup/SKILL.md +75 -0
- package/plugins/lisa-wiki-devin/skills/lisa-wiki-setup-automations/SKILL.md +83 -0
- package/plugins/lisa-wiki-devin/skills/lisa-wiki-status/SKILL.md +47 -0
- package/plugins/lisa-wiki-devin/skills/lisa-wiki-tear-down-automations/SKILL.md +34 -0
- package/plugins/lisa-wiki-devin/skills/lisa-wiki-usage/SKILL.md +50 -0
- package/plugins/lisa-wiki-devin/templates/agents/role-agent.claude.md +16 -0
- package/plugins/lisa-wiki-devin/templates/agents/role-agent.codex.toml +15 -0
- package/plugins/lisa-wiki-devin/templates/index.md +17 -0
- package/plugins/lisa-wiki-devin/templates/llm-wiki-contract.md +72 -0
- package/plugins/lisa-wiki-devin/templates/log.md +8 -0
- package/plugins/lisa-wiki-devin/templates/page-types/architecture.md +18 -0
- package/plugins/lisa-wiki-devin/templates/page-types/concept.md +18 -0
- package/plugins/lisa-wiki-devin/templates/page-types/decision.md +18 -0
- package/plugins/lisa-wiki-devin/templates/page-types/entity.md +19 -0
- package/plugins/lisa-wiki-devin/templates/page-types/open-question.md +18 -0
- package/plugins/lisa-wiki-devin/templates/page-types/playbook.md +18 -0
- package/plugins/lisa-wiki-devin/templates/page-types/project.md +19 -0
- package/plugins/lisa-wiki-devin/templates/page-types/requirement.md +19 -0
- package/plugins/lisa-wiki-devin/templates/page-types/staff.md +26 -0
- package/plugins/lisa-wiki-devin/templates/start-here.md +24 -0
- package/plugins/lisa-wiki-devin/templates/state-readme.md +20 -0
- package/plugins/lisa-wiki-devin/templates/wrapper-gitignore.txt +19 -0
- package/scripts/build-plugins.sh +2 -2
- package/scripts/deployed-guard-advice.mjs +1 -0
- package/scripts/generate-devin-plugin-artifacts.mjs +263 -0
- package/scripts/lib/hook-registration-audit.mjs +3 -1
- package/scripts/lib/per-agent-hook-filter.mjs +174 -5
- package/scripts/lib/plugin-rule-citations.mjs +2 -2
|
@@ -0,0 +1,1081 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Shared Codex runtime adapter for `/lisa:automation-status`.
|
|
4
|
+
*
|
|
5
|
+
* This adapter inspects the local Codex automation backing store read-only:
|
|
6
|
+
* the per-automation `automation.toml` contract plus the automation memory file
|
|
7
|
+
* used by recurring runs. It scopes the scan to the current repo's expected
|
|
8
|
+
* Lisa automation prefix, derives normalized command/cadence metadata, and
|
|
9
|
+
* overlays available recency/failure signals onto the shared fleet report
|
|
10
|
+
* contract.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import fs from "node:fs/promises";
|
|
14
|
+
import { constants as fsConstants } from "node:fs";
|
|
15
|
+
import os from "node:os";
|
|
16
|
+
import path from "node:path";
|
|
17
|
+
import { execFile } from "node:child_process";
|
|
18
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
19
|
+
import { promisify } from "node:util";
|
|
20
|
+
|
|
21
|
+
import { compareAutomationFleet } from "./automation-status-contract-drift.mjs";
|
|
22
|
+
import {
|
|
23
|
+
assignToAutomationGroup,
|
|
24
|
+
createAutomationGroupBins,
|
|
25
|
+
renderAutomationGroups,
|
|
26
|
+
} from "./automation-status-expected-fleet.mjs";
|
|
27
|
+
import {
|
|
28
|
+
RUNBOOK_NOT_SCAFFOLDED_LINE,
|
|
29
|
+
resolveAutomationRunDisplay,
|
|
30
|
+
resolveLedgerIntegrityFinding,
|
|
31
|
+
resolveRecoveryEscalation,
|
|
32
|
+
} from "./automation-status-run-history.mjs";
|
|
33
|
+
import { resolveUnrecordedRunFinding } from "./automation-status-unrecorded-runs.mjs";
|
|
34
|
+
|
|
35
|
+
const CODEx_RUNTIME_LABEL = "Codex automations";
|
|
36
|
+
const RUN_TIMESTAMP_PATTERN = /20\d{2}-\d\d-\d\dT\d\d:\d\d:\d\d(?:\.\d+)?Z/;
|
|
37
|
+
const RUN_FAILURE_PATTERN =
|
|
38
|
+
/\b(failed|failure|errored|error|exception|crash(?:ed)?)\b/i;
|
|
39
|
+
const NEGATED_FAILURE_PATTERN =
|
|
40
|
+
/\b(no|without)\s+(?:recent\s+)?(?:fail(?:ure|ed)|errors?|exceptions?)\b/i;
|
|
41
|
+
const execFileAsync = promisify(execFile);
|
|
42
|
+
const MAX_SCHEDULER_ENTRIES = 1_000;
|
|
43
|
+
const MAX_MATCHING_AUTOMATIONS = 100;
|
|
44
|
+
const MAX_AUTOMATION_TOML_BYTES = 256 * 1024;
|
|
45
|
+
const MAX_AUTOMATION_MEMORY_BYTES = 512 * 1024;
|
|
46
|
+
const READ_CHUNK_BYTES = 64 * 1024;
|
|
47
|
+
const UNSAFE_SCHEDULER_FILE = "Unsafe Codex scheduler file";
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Git location env vars that, when inherited, override the `-C <dir>` flag and
|
|
51
|
+
* cwd. When this adapter runs inside a Git hook (e.g. pre-push) these are
|
|
52
|
+
* exported by Git, so a `git -C <cwd> rev-parse` would answer about the hook's
|
|
53
|
+
* repository instead of the inspected automation cwd — misreporting every
|
|
54
|
+
* healthy automation as FAILING. They must be scrubbed so `-C`/cwd governs.
|
|
55
|
+
*/
|
|
56
|
+
const GIT_LOCATION_ENV_VARS = [
|
|
57
|
+
"GIT_DIR",
|
|
58
|
+
"GIT_WORK_TREE",
|
|
59
|
+
"GIT_INDEX_FILE",
|
|
60
|
+
"GIT_OBJECT_DIRECTORY",
|
|
61
|
+
"GIT_ALTERNATE_OBJECT_DIRECTORIES",
|
|
62
|
+
"GIT_COMMON_DIR",
|
|
63
|
+
"GIT_NAMESPACE",
|
|
64
|
+
"GIT_PREFIX",
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Process-spawn failures that are transient under heavy fork load (the OS could
|
|
69
|
+
* not start the child, not git reporting a result). Retrying these avoids
|
|
70
|
+
* misclassifying a healthy cwd as a `git_error` when the machine is saturated.
|
|
71
|
+
*/
|
|
72
|
+
const TRANSIENT_SPAWN_ERROR_CODES = new Set([
|
|
73
|
+
"EAGAIN",
|
|
74
|
+
"ENOMEM",
|
|
75
|
+
"EMFILE",
|
|
76
|
+
"ENFILE",
|
|
77
|
+
"ETXTBSY",
|
|
78
|
+
]);
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Build a git-safe environment: the ambient process env minus the location
|
|
82
|
+
* overrides so a `-C <dir>` invocation targets the intended directory.
|
|
83
|
+
*
|
|
84
|
+
* @returns {NodeJS.ProcessEnv}
|
|
85
|
+
*/
|
|
86
|
+
function gitEnvWithoutLocationOverrides() {
|
|
87
|
+
const env = { ...process.env };
|
|
88
|
+
for (const key of GIT_LOCATION_ENV_VARS) {
|
|
89
|
+
delete env[key];
|
|
90
|
+
}
|
|
91
|
+
return env;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Run `git` against an explicit directory, immune to inherited Git location env
|
|
96
|
+
* vars, with a bounded retry on transient process-spawn failures. A git process
|
|
97
|
+
* that actually ran — success or non-zero exit — is surfaced unchanged on the
|
|
98
|
+
* first attempt; only failures to launch the child at all are retried.
|
|
99
|
+
*
|
|
100
|
+
* @param {readonly string[]} args git arguments
|
|
101
|
+
* @param {import("node:child_process").ExecFileOptions} [options]
|
|
102
|
+
* @param {number} [attempts] maximum attempts (default 4)
|
|
103
|
+
* @returns {Promise<{ stdout: string, stderr: string }>}
|
|
104
|
+
*/
|
|
105
|
+
async function execGitWithRetry(args, options, attempts = 4) {
|
|
106
|
+
const mergedOptions = { ...options, env: gitEnvWithoutLocationOverrides() };
|
|
107
|
+
for (let attempt = 1; ; attempt += 1) {
|
|
108
|
+
try {
|
|
109
|
+
return await execFileAsync("git", args, mergedOptions);
|
|
110
|
+
} catch (error) {
|
|
111
|
+
const transient = TRANSIENT_SPAWN_ERROR_CODES.has(error?.code);
|
|
112
|
+
if (!transient || attempt >= attempts) {
|
|
113
|
+
throw error;
|
|
114
|
+
}
|
|
115
|
+
await delay(2 ** attempt * 25, undefined, {
|
|
116
|
+
signal: options?.signal,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* @typedef {import("./automation-status-expected-fleet.mjs").resolveExpectedAutomationFleet extends (...args: any[]) => infer T ? T : never} ExpectedFleet
|
|
124
|
+
*
|
|
125
|
+
* @typedef {{
|
|
126
|
+
* readonly automationId: string
|
|
127
|
+
* readonly status?: string
|
|
128
|
+
* readonly prompt?: string
|
|
129
|
+
* readonly observedCadence?: string
|
|
130
|
+
* readonly observedRRule?: string
|
|
131
|
+
* readonly observedCommand?: string
|
|
132
|
+
* readonly cwd?: string | null
|
|
133
|
+
* readonly cwdHealth?: {
|
|
134
|
+
* readonly status: "ok" | "missing" | "not_directory" | "not_git_work_tree" | "bare_git_repository" | "git_error"
|
|
135
|
+
* readonly summary: string
|
|
136
|
+
* }
|
|
137
|
+
* readonly createdAt?: number | null
|
|
138
|
+
* readonly updatedAt?: number | null
|
|
139
|
+
* readonly lastRunAt?: string | null
|
|
140
|
+
* readonly lastRunSummary?: string | null
|
|
141
|
+
* readonly lastRunFailed?: boolean
|
|
142
|
+
* }} ObservedCodexAutomation
|
|
143
|
+
*/
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Inspect the current repo's Codex automation fleet and map it to the shared
|
|
147
|
+
* automation-status report contract.
|
|
148
|
+
*
|
|
149
|
+
* @param {{
|
|
150
|
+
* readonly expectedFleet: ExpectedFleet
|
|
151
|
+
* readonly automationsDir?: string
|
|
152
|
+
* readonly projectRoot?: string
|
|
153
|
+
* readonly now?: string | Date
|
|
154
|
+
* }} input
|
|
155
|
+
* @returns {Promise<{
|
|
156
|
+
* readonly runtime: string
|
|
157
|
+
* readonly generatedAt: string
|
|
158
|
+
* readonly groups: readonly {
|
|
159
|
+
* readonly id: string
|
|
160
|
+
* readonly title: string
|
|
161
|
+
* readonly items: readonly {
|
|
162
|
+
* readonly id: string
|
|
163
|
+
* readonly status: "HEALTHY" | "MISSING" | "UNSUPPORTED" | "DRIFTED" | "STALE" | "FAILING"
|
|
164
|
+
* readonly summary: string
|
|
165
|
+
* readonly expectedCadence?: string
|
|
166
|
+
* readonly expectedCommand?: string
|
|
167
|
+
* readonly observed?: string
|
|
168
|
+
* readonly runbook?: string
|
|
169
|
+
* readonly lastOutcome?: { readonly ts: string, readonly outcome: string, readonly summary: string }
|
|
170
|
+
* readonly outcomeHistory?: readonly string[]
|
|
171
|
+
* readonly olderRecordCount?: number
|
|
172
|
+
* readonly remediation?: string
|
|
173
|
+
* }[]
|
|
174
|
+
* }[]
|
|
175
|
+
* readonly observedAutomations: readonly ObservedCodexAutomation[]
|
|
176
|
+
* }>}
|
|
177
|
+
*/
|
|
178
|
+
export async function inspectCodexAutomationFleet(input) {
|
|
179
|
+
const expectedFleet = input.expectedFleet;
|
|
180
|
+
const now = normalizeDate(input.now);
|
|
181
|
+
const projectRoot = input.projectRoot ?? process.cwd();
|
|
182
|
+
const observedAutomations = await listCodexAutomations({
|
|
183
|
+
automationsDir: input.automationsDir,
|
|
184
|
+
automationPrefix: expectedFleet.automationPrefix,
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
const runDisplays = await resolveFleetRunDisplays(projectRoot, expectedFleet);
|
|
188
|
+
|
|
189
|
+
const expectedGroups = createAutomationGroupBins();
|
|
190
|
+
|
|
191
|
+
const comparisons = compareAutomationFleet({
|
|
192
|
+
expectedAutomations: expectedFleet.expected,
|
|
193
|
+
observedAutomations,
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
for (const [index, expected] of expectedFleet.expected.entries()) {
|
|
197
|
+
const comparison = comparisons[index];
|
|
198
|
+
assignToAutomationGroup(
|
|
199
|
+
expectedGroups,
|
|
200
|
+
expected.group,
|
|
201
|
+
createObservedStatusItem({
|
|
202
|
+
expected,
|
|
203
|
+
comparison,
|
|
204
|
+
now,
|
|
205
|
+
runDisplay: runDisplays.get(expected.id),
|
|
206
|
+
})
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
for (const unsupported of expectedFleet.unsupported) {
|
|
211
|
+
const runDisplay = runDisplays.get(unsupported.id);
|
|
212
|
+
assignToAutomationGroup(expectedGroups, unsupported.group, {
|
|
213
|
+
id: unsupported.automationId,
|
|
214
|
+
status: "UNSUPPORTED",
|
|
215
|
+
summary: unsupported.reason,
|
|
216
|
+
expectedCadence: unsupported.expectedCadence,
|
|
217
|
+
observed: "No automation is expected for this repo/runtime combination.",
|
|
218
|
+
runbook: runDisplay?.runbook,
|
|
219
|
+
lastOutcome: runDisplay?.lastOutcome,
|
|
220
|
+
outcomeHistory: runDisplay?.outcomeHistory,
|
|
221
|
+
olderRecordCount: runDisplay?.olderRecordCount,
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return {
|
|
226
|
+
runtime: `${CODEx_RUNTIME_LABEL} (backing-store metadata)`,
|
|
227
|
+
generatedAt: now.toISOString(),
|
|
228
|
+
groups: renderAutomationGroups(expectedGroups),
|
|
229
|
+
observedAutomations,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Read every Codex automation whose id matches the current repo's Lisa prefix.
|
|
235
|
+
*
|
|
236
|
+
* @param {{
|
|
237
|
+
* readonly automationsDir?: string
|
|
238
|
+
* readonly automationPrefix: string
|
|
239
|
+
* readonly signal?: AbortSignal
|
|
240
|
+
* }} input
|
|
241
|
+
* @returns {Promise<readonly ObservedCodexAutomation[]>}
|
|
242
|
+
*/
|
|
243
|
+
export async function listCodexAutomations(input) {
|
|
244
|
+
input.signal?.throwIfAborted();
|
|
245
|
+
const requestedRoot =
|
|
246
|
+
input.automationsDir ?? resolveDefaultCodexAutomationsDir();
|
|
247
|
+
const automationsRoot = await fs.realpath(requestedRoot);
|
|
248
|
+
input.signal?.throwIfAborted();
|
|
249
|
+
const automationDirs = await listConfinedAutomationDirectories(
|
|
250
|
+
automationsRoot,
|
|
251
|
+
input.automationPrefix,
|
|
252
|
+
input.signal
|
|
253
|
+
);
|
|
254
|
+
return await readCodexAutomations(automationDirs, input.signal);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Enumerate a bounded number of direct, regular scheduler directories.
|
|
259
|
+
* @param {string} automationsRoot Canonical scheduler root.
|
|
260
|
+
* @param {string} automationPrefix Expected repository automation prefix.
|
|
261
|
+
* @param {AbortSignal | undefined} signal Probe cancellation signal.
|
|
262
|
+
* @returns {Promise<readonly string[]>} Canonical matching directories.
|
|
263
|
+
*/
|
|
264
|
+
async function listConfinedAutomationDirectories(
|
|
265
|
+
automationsRoot,
|
|
266
|
+
automationPrefix,
|
|
267
|
+
signal
|
|
268
|
+
) {
|
|
269
|
+
const directory = await fs.opendir(automationsRoot);
|
|
270
|
+
try {
|
|
271
|
+
const names = await readBoundedDirectoryNames(
|
|
272
|
+
directory,
|
|
273
|
+
automationPrefix,
|
|
274
|
+
signal
|
|
275
|
+
);
|
|
276
|
+
const directories = await Promise.all(
|
|
277
|
+
names.map(name => confinedAutomationDirectory(automationsRoot, name))
|
|
278
|
+
);
|
|
279
|
+
signal?.throwIfAborted();
|
|
280
|
+
return directories.toSorted((left, right) => left.localeCompare(right));
|
|
281
|
+
} finally {
|
|
282
|
+
await closeDirectory(directory);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Close a scheduler directory while tolerating runtimes that auto-close it
|
|
288
|
+
* after async iteration.
|
|
289
|
+
* @param {import("node:fs").Dir} directory Open scheduler directory handle.
|
|
290
|
+
* @returns {Promise<void>}
|
|
291
|
+
*/
|
|
292
|
+
async function closeDirectory(directory) {
|
|
293
|
+
try {
|
|
294
|
+
await directory.close();
|
|
295
|
+
} catch (error) {
|
|
296
|
+
if (error?.code !== "ERR_DIR_CLOSED") throw error;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Consume directory entries with total and prefix-match bounds.
|
|
302
|
+
* @param {import("node:fs").Dir} directory Open scheduler directory handle.
|
|
303
|
+
* @param {string} automationPrefix Expected repository automation prefix.
|
|
304
|
+
* @param {AbortSignal | undefined} signal Probe cancellation signal.
|
|
305
|
+
* @param {number} [entryCount] Entries consumed so far.
|
|
306
|
+
* @param {readonly string[]} [matchingNames] Matching directory names.
|
|
307
|
+
* @returns {Promise<readonly string[]>} Bounded matching names.
|
|
308
|
+
*/
|
|
309
|
+
async function readBoundedDirectoryNames(
|
|
310
|
+
directory,
|
|
311
|
+
automationPrefix,
|
|
312
|
+
signal,
|
|
313
|
+
entryCount = 0,
|
|
314
|
+
matchingNames = []
|
|
315
|
+
) {
|
|
316
|
+
signal?.throwIfAborted();
|
|
317
|
+
if (entryCount >= MAX_SCHEDULER_ENTRIES) {
|
|
318
|
+
const overflow = await directory.read();
|
|
319
|
+
if (overflow !== null) {
|
|
320
|
+
throw new Error("Codex scheduler enumeration exceeds entry limit");
|
|
321
|
+
}
|
|
322
|
+
return matchingNames;
|
|
323
|
+
}
|
|
324
|
+
const entry = await directory.read();
|
|
325
|
+
signal?.throwIfAborted();
|
|
326
|
+
if (entry === null) return matchingNames;
|
|
327
|
+
const matches =
|
|
328
|
+
entry.isDirectory() && entry.name.startsWith(automationPrefix);
|
|
329
|
+
const nextNames = matches ? [...matchingNames, entry.name] : matchingNames;
|
|
330
|
+
if (nextNames.length > MAX_MATCHING_AUTOMATIONS) {
|
|
331
|
+
throw new Error("Codex scheduler automation count exceeds limit");
|
|
332
|
+
}
|
|
333
|
+
return await readBoundedDirectoryNames(
|
|
334
|
+
directory,
|
|
335
|
+
automationPrefix,
|
|
336
|
+
signal,
|
|
337
|
+
entryCount + 1,
|
|
338
|
+
nextNames
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Verify one direct scheduler entry remains a confined real directory.
|
|
344
|
+
* @param {string} automationsRoot Canonical scheduler root.
|
|
345
|
+
* @param {string} name Direct entry name.
|
|
346
|
+
* @returns {Promise<string>} Canonical automation directory.
|
|
347
|
+
*/
|
|
348
|
+
async function confinedAutomationDirectory(automationsRoot, name) {
|
|
349
|
+
const candidate = path.join(automationsRoot, name);
|
|
350
|
+
const stat = await fs.lstat(candidate);
|
|
351
|
+
if (!stat.isDirectory() || stat.isSymbolicLink()) {
|
|
352
|
+
throw new Error("Unsafe Codex scheduler directory");
|
|
353
|
+
}
|
|
354
|
+
const actual = await fs.realpath(candidate);
|
|
355
|
+
if (!actual.startsWith(`${automationsRoot}${path.sep}`)) {
|
|
356
|
+
throw new Error("Codex scheduler directory escapes root");
|
|
357
|
+
}
|
|
358
|
+
return actual;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Read scheduler entries sequentially to bound simultaneously open files.
|
|
363
|
+
* @param {readonly string[]} automationDirs Canonical automation directories.
|
|
364
|
+
* @param {AbortSignal | undefined} signal Probe cancellation signal.
|
|
365
|
+
* @param {number} [index] Next directory index.
|
|
366
|
+
* @param {readonly ObservedCodexAutomation[]} [results] Completed observations.
|
|
367
|
+
* @returns {Promise<readonly ObservedCodexAutomation[]>} Observations.
|
|
368
|
+
*/
|
|
369
|
+
async function readCodexAutomations(
|
|
370
|
+
automationDirs,
|
|
371
|
+
signal,
|
|
372
|
+
index = 0,
|
|
373
|
+
results = []
|
|
374
|
+
) {
|
|
375
|
+
signal?.throwIfAborted();
|
|
376
|
+
if (index >= automationDirs.length) return results;
|
|
377
|
+
const observation = await readCodexAutomation(automationDirs[index], signal);
|
|
378
|
+
return await readCodexAutomations(automationDirs, signal, index + 1, [
|
|
379
|
+
...results,
|
|
380
|
+
observation,
|
|
381
|
+
]);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Normalize a Lisa Codex automation prompt back into the slash-command surface
|
|
386
|
+
* expected by the shared drift classifier.
|
|
387
|
+
*
|
|
388
|
+
* @param {string | undefined} prompt
|
|
389
|
+
* @returns {string | undefined}
|
|
390
|
+
*/
|
|
391
|
+
export function deriveCodexObservedCommand(prompt) {
|
|
392
|
+
if (!prompt) {
|
|
393
|
+
return undefined;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// The "with arguments" clause is optional: no-argument loops (monitor, the
|
|
397
|
+
// gardener) register without one. Requiring it made every such loop derive an
|
|
398
|
+
// undefined command and report DRIFTED forever, un-fixable by re-running setup.
|
|
399
|
+
const lisaSkillMatch = prompt.match(
|
|
400
|
+
/Use the Lisa ([a-z0-9:-]+) skill(?: with arguments `([^`]*)`)?/i
|
|
401
|
+
);
|
|
402
|
+
if (lisaSkillMatch?.[1]) {
|
|
403
|
+
return `/lisa:${lisaSkillMatch[1]} ${lisaSkillMatch[2] ?? ""}`.trim();
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
const aliasSkillMatch = prompt.match(
|
|
407
|
+
/Use the `\$([a-z0-9:-]+)` skill(?: with arguments `([^`]*)`)?/i
|
|
408
|
+
);
|
|
409
|
+
if (aliasSkillMatch?.[1]) {
|
|
410
|
+
return `${canonicalizeCodexSkillAlias(aliasSkillMatch[1])} ${aliasSkillMatch[2] ?? ""}`.trim();
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// A registration whose prompt carries the literal Lisa command on its own
|
|
414
|
+
// line — the shape `/lisa:setup-automations` bakes so a command that is not a
|
|
415
|
+
// plain skill name (`/lisa:learnings:audit`) round-trips exactly. Mirrors the
|
|
416
|
+
// Claude adapter, which has always accepted a bare `/lisa:` command. Codex
|
|
417
|
+
// stores prompts as single-line TOML, so a line break arrives either real or
|
|
418
|
+
// as the two-character escape `\n`; both delimit a line here.
|
|
419
|
+
const literalCommand = prompt
|
|
420
|
+
.split(/\r?\n|\\n/)
|
|
421
|
+
.map(segment => segment.trim())
|
|
422
|
+
.find(segment => /^\/lisa[:-]\S/.test(segment));
|
|
423
|
+
|
|
424
|
+
return literalCommand;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
function canonicalizeCodexSkillAlias(alias) {
|
|
428
|
+
if (alias.startsWith("lisa-")) {
|
|
429
|
+
return `/lisa:${alias.slice("lisa-".length)}`;
|
|
430
|
+
}
|
|
431
|
+
return `/${alias}`;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Parse the latest run metadata from an automation memory file.
|
|
436
|
+
*
|
|
437
|
+
* @param {string | undefined} memoryContent
|
|
438
|
+
* @returns {{
|
|
439
|
+
* readonly lastRunAt: string | null
|
|
440
|
+
* readonly lastRunSummary: string | null
|
|
441
|
+
* readonly lastRunFailed: boolean
|
|
442
|
+
* }}
|
|
443
|
+
*/
|
|
444
|
+
export function parseCodexAutomationMemory(memoryContent) {
|
|
445
|
+
if (!memoryContent) {
|
|
446
|
+
return {
|
|
447
|
+
lastRunAt: null,
|
|
448
|
+
lastRunSummary: null,
|
|
449
|
+
lastRunFailed: false,
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
const lines = memoryContent.split(/\r?\n/);
|
|
454
|
+
const latestBlock = findLatestAutomationMemoryBlock(lines);
|
|
455
|
+
const summaryLine =
|
|
456
|
+
latestBlock.lines
|
|
457
|
+
.find(line => line.startsWith("- "))
|
|
458
|
+
?.replace(/^- /, "")
|
|
459
|
+
.trim() ?? null;
|
|
460
|
+
|
|
461
|
+
const latestBlockText = latestBlock.lines.join("\n");
|
|
462
|
+
const lastRunFailed =
|
|
463
|
+
RUN_FAILURE_PATTERN.test(latestBlockText) &&
|
|
464
|
+
!NEGATED_FAILURE_PATTERN.test(latestBlockText);
|
|
465
|
+
|
|
466
|
+
return {
|
|
467
|
+
lastRunAt: latestBlock.timestamp,
|
|
468
|
+
lastRunSummary: summaryLine,
|
|
469
|
+
lastRunFailed,
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
function findLatestAutomationMemoryBlock(lines) {
|
|
474
|
+
const timestampLines = lines
|
|
475
|
+
.map((line, index) => ({
|
|
476
|
+
index,
|
|
477
|
+
timestamp: line.match(RUN_TIMESTAMP_PATTERN)?.[0] ?? null,
|
|
478
|
+
}))
|
|
479
|
+
.filter(entry => entry.timestamp);
|
|
480
|
+
|
|
481
|
+
if (timestampLines.length === 0) {
|
|
482
|
+
return {
|
|
483
|
+
timestamp: null,
|
|
484
|
+
lines,
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
const latest = timestampLines.at(-1);
|
|
489
|
+
const next = timestampLines.find(entry => entry.index > latest.index);
|
|
490
|
+
|
|
491
|
+
return {
|
|
492
|
+
timestamp: latest.timestamp,
|
|
493
|
+
lines: lines.slice(latest.index, next?.index),
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
/**
|
|
498
|
+
* Read one stable bounded file without following a scheduler symlink or FIFO.
|
|
499
|
+
* @param {string} automationDir Canonical automation directory.
|
|
500
|
+
* @param {string} filename Direct scheduler filename.
|
|
501
|
+
* @param {number} maximumBytes Maximum allowed bytes.
|
|
502
|
+
* @param {AbortSignal | undefined} signal Probe cancellation signal.
|
|
503
|
+
* @param {boolean} [optional] Whether a missing file resolves to undefined.
|
|
504
|
+
* @returns {Promise<string | undefined>} Strict UTF-8 contents.
|
|
505
|
+
*/
|
|
506
|
+
async function readConfinedSchedulerText(
|
|
507
|
+
automationDir,
|
|
508
|
+
filename,
|
|
509
|
+
maximumBytes,
|
|
510
|
+
signal,
|
|
511
|
+
optional = false
|
|
512
|
+
) {
|
|
513
|
+
signal?.throwIfAborted();
|
|
514
|
+
const target = path.join(automationDir, filename);
|
|
515
|
+
const before = await fs.lstat(target).catch(error => {
|
|
516
|
+
if (optional && error?.code === "ENOENT") return null;
|
|
517
|
+
throw error;
|
|
518
|
+
});
|
|
519
|
+
if (before === null) return undefined;
|
|
520
|
+
assertBoundedSchedulerFile(before, maximumBytes);
|
|
521
|
+
const actual = await fs.realpath(target);
|
|
522
|
+
if (!actual.startsWith(`${automationDir}${path.sep}`)) {
|
|
523
|
+
throw new Error("Codex scheduler file escapes automation directory");
|
|
524
|
+
}
|
|
525
|
+
const handle = await fs.open(
|
|
526
|
+
target,
|
|
527
|
+
fsConstants.O_RDONLY | fsConstants.O_NOFOLLOW | fsConstants.O_NONBLOCK
|
|
528
|
+
);
|
|
529
|
+
try {
|
|
530
|
+
const opened = await handle.stat();
|
|
531
|
+
assertBoundedSchedulerFile(opened, maximumBytes);
|
|
532
|
+
if (opened.dev !== before.dev || opened.ino !== before.ino) {
|
|
533
|
+
throw new Error("Codex scheduler file changed during inspection");
|
|
534
|
+
}
|
|
535
|
+
const bytes = await readBoundedSchedulerFile(handle, maximumBytes, signal);
|
|
536
|
+
const after = await handle.stat();
|
|
537
|
+
if (after.size !== opened.size || bytes.length !== after.size) {
|
|
538
|
+
throw new Error("Codex scheduler file changed during read");
|
|
539
|
+
}
|
|
540
|
+
signal?.throwIfAborted();
|
|
541
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
542
|
+
} finally {
|
|
543
|
+
await handle.close();
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
/**
|
|
548
|
+
* Reject non-regular and oversized scheduler files before opening them.
|
|
549
|
+
* @param {import("node:fs").Stats} stat Scheduler file metadata.
|
|
550
|
+
* @param {number} maximumBytes Maximum allowed bytes.
|
|
551
|
+
* @returns {void}
|
|
552
|
+
*/
|
|
553
|
+
function assertBoundedSchedulerFile(stat, maximumBytes) {
|
|
554
|
+
if (!stat.isFile() || stat.isSymbolicLink()) {
|
|
555
|
+
throw new Error(UNSAFE_SCHEDULER_FILE);
|
|
556
|
+
}
|
|
557
|
+
if (stat.size > maximumBytes) {
|
|
558
|
+
throw new Error("Codex scheduler file exceeds size limit");
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* Read at most maximum plus one bytes from an already confined file handle.
|
|
564
|
+
* @param {import("node:fs/promises").FileHandle} handle Open file handle.
|
|
565
|
+
* @param {number} maximumBytes Maximum allowed bytes.
|
|
566
|
+
* @param {AbortSignal | undefined} signal Probe cancellation signal.
|
|
567
|
+
* @param {number} [offset] Current file offset.
|
|
568
|
+
* @returns {Promise<Buffer>} Bounded bytes.
|
|
569
|
+
*/
|
|
570
|
+
async function readBoundedSchedulerFile(
|
|
571
|
+
handle,
|
|
572
|
+
maximumBytes,
|
|
573
|
+
signal,
|
|
574
|
+
offset = 0
|
|
575
|
+
) {
|
|
576
|
+
signal?.throwIfAborted();
|
|
577
|
+
const remaining = maximumBytes + 1 - offset;
|
|
578
|
+
if (remaining <= 0) {
|
|
579
|
+
throw new Error("Codex scheduler file exceeds size limit");
|
|
580
|
+
}
|
|
581
|
+
const chunk = Buffer.allocUnsafe(Math.min(READ_CHUNK_BYTES, remaining));
|
|
582
|
+
const { bytesRead } = await handle.read(chunk, 0, chunk.length, offset);
|
|
583
|
+
signal?.throwIfAborted();
|
|
584
|
+
if (bytesRead === 0) return Buffer.alloc(0);
|
|
585
|
+
const current = chunk.subarray(0, bytesRead);
|
|
586
|
+
const tail = await readBoundedSchedulerFile(
|
|
587
|
+
handle,
|
|
588
|
+
maximumBytes,
|
|
589
|
+
signal,
|
|
590
|
+
offset + bytesRead
|
|
591
|
+
);
|
|
592
|
+
return Buffer.concat([current, tail], bytesRead + tail.length);
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
/**
|
|
596
|
+
* Read one confined Codex automation contract and optional memory.
|
|
597
|
+
* @param {string} automationDir Canonical automation directory.
|
|
598
|
+
* @param {AbortSignal | undefined} signal Probe cancellation signal.
|
|
599
|
+
* @returns {Promise<ObservedCodexAutomation>} Normalized observation.
|
|
600
|
+
*/
|
|
601
|
+
async function readCodexAutomation(automationDir, signal) {
|
|
602
|
+
const tomlContent = await readConfinedSchedulerText(
|
|
603
|
+
automationDir,
|
|
604
|
+
"automation.toml",
|
|
605
|
+
MAX_AUTOMATION_TOML_BYTES,
|
|
606
|
+
signal
|
|
607
|
+
);
|
|
608
|
+
const automation = parseAutomationToml(tomlContent);
|
|
609
|
+
const memoryContent =
|
|
610
|
+
(await readConfinedSchedulerText(
|
|
611
|
+
automationDir,
|
|
612
|
+
"memory.md",
|
|
613
|
+
MAX_AUTOMATION_MEMORY_BYTES,
|
|
614
|
+
signal,
|
|
615
|
+
true
|
|
616
|
+
)) ?? "";
|
|
617
|
+
const memory = parseCodexAutomationMemory(memoryContent);
|
|
618
|
+
const cwd = Array.isArray(automation.cwds) ? automation.cwds[0] : null;
|
|
619
|
+
const normalizedCwd = typeof cwd === "string" ? cwd : null;
|
|
620
|
+
const cwdHealth = await inspectAutomationCwd(normalizedCwd, signal);
|
|
621
|
+
|
|
622
|
+
return {
|
|
623
|
+
automationId:
|
|
624
|
+
stringOrUndefined(automation.id) ?? path.basename(automationDir),
|
|
625
|
+
status: stringOrUndefined(automation.status),
|
|
626
|
+
prompt: stringOrUndefined(automation.prompt),
|
|
627
|
+
observedCadence: humanizeAutomationCadence(
|
|
628
|
+
stringOrUndefined(automation.rrule)
|
|
629
|
+
),
|
|
630
|
+
observedRRule: stringOrUndefined(automation.rrule),
|
|
631
|
+
observedCommand: deriveCodexObservedCommand(
|
|
632
|
+
stringOrUndefined(automation.prompt)
|
|
633
|
+
),
|
|
634
|
+
cwd: normalizedCwd,
|
|
635
|
+
cwdHealth,
|
|
636
|
+
createdAt: numberOrNull(automation.created_at),
|
|
637
|
+
updatedAt: numberOrNull(automation.updated_at),
|
|
638
|
+
...memory,
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
/**
|
|
643
|
+
* Read the read-only run-history display for every expected and unsupported
|
|
644
|
+
* loop up front, keyed by the loop's short id, so the per-entry item builder
|
|
645
|
+
* stays synchronous.
|
|
646
|
+
*
|
|
647
|
+
* @param {string} projectRoot
|
|
648
|
+
* @param {ExpectedFleet} expectedFleet
|
|
649
|
+
* @returns {Promise<Map<string, import("./automation-status-run-history.mjs").AutomationRunDisplay>>}
|
|
650
|
+
*/
|
|
651
|
+
async function resolveFleetRunDisplays(projectRoot, expectedFleet) {
|
|
652
|
+
const entries = [...expectedFleet.expected, ...expectedFleet.unsupported];
|
|
653
|
+
const displays = await Promise.all(
|
|
654
|
+
entries.map(entry =>
|
|
655
|
+
resolveAutomationRunDisplay({
|
|
656
|
+
projectRoot,
|
|
657
|
+
loopId: entry.id,
|
|
658
|
+
runbookPath: entry.runbookPath,
|
|
659
|
+
})
|
|
660
|
+
)
|
|
661
|
+
);
|
|
662
|
+
return new Map(entries.map((entry, index) => [entry.id, displays[index]]));
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
function createObservedStatusItem(input) {
|
|
666
|
+
const expected = input.expected;
|
|
667
|
+
const comparison = input.comparison;
|
|
668
|
+
const observed = comparison.observedAutomation;
|
|
669
|
+
const runDisplay = input.runDisplay;
|
|
670
|
+
const primaryRunSignal = classifyAutomationRunSignal({
|
|
671
|
+
expected,
|
|
672
|
+
observedAutomation: observed,
|
|
673
|
+
now: input.now,
|
|
674
|
+
});
|
|
675
|
+
// Three or more consecutive recorded recovery-required runs flip the loop to
|
|
676
|
+
// FAILING even when the scheduler entry looks fine — the fleet-health signal
|
|
677
|
+
// the raw backing store cannot see. It wins over the scheduler run-signal.
|
|
678
|
+
const escalation = resolveRecoveryEscalation(runDisplay);
|
|
679
|
+
|
|
680
|
+
// A run the scheduler saw but the ledger did not. Ranked below
|
|
681
|
+
// `primaryRunSignal` on purpose: a suspended entry or a broken cwd EXPLAINS
|
|
682
|
+
// the missing rows, so reporting the silence over the cause would bury it.
|
|
683
|
+
const unrecorded = resolveUnrecordedRunFinding({
|
|
684
|
+
schedulerLastRunAt: observed?.lastRunAt,
|
|
685
|
+
ledgerLastRecordAt: runDisplay?.lastOutcome?.ts ?? null,
|
|
686
|
+
hasRunbook: runDisplay
|
|
687
|
+
? runDisplay.runbook !== RUNBOOK_NOT_SCAFFOLDED_LINE
|
|
688
|
+
: undefined,
|
|
689
|
+
cadenceMs: observed
|
|
690
|
+
? resolveObservedCadenceMs({ observed, expected })
|
|
691
|
+
: null,
|
|
692
|
+
});
|
|
693
|
+
// Ranked last of the three. A suspended scheduler entry, or a run the ledger
|
|
694
|
+
// never received, describes the loop; unreadable rows describe the ledger.
|
|
695
|
+
// Reporting the storage problem over either cause would bury the cause — but
|
|
696
|
+
// with nothing else to say, it is said rather than counted where nobody
|
|
697
|
+
// looks (#2578).
|
|
698
|
+
const ledgerIntegrity = resolveLedgerIntegrityFinding(runDisplay);
|
|
699
|
+
const runSignal =
|
|
700
|
+
primaryRunSignal ??
|
|
701
|
+
(unrecorded && {
|
|
702
|
+
status: /** @type {const} */ ("DRIFTED"),
|
|
703
|
+
summary: unrecorded.summary,
|
|
704
|
+
remediation: unrecorded.remediation,
|
|
705
|
+
}) ??
|
|
706
|
+
ledgerIntegrity;
|
|
707
|
+
|
|
708
|
+
const observedDetails = [comparison.observed];
|
|
709
|
+
if (observed?.status) {
|
|
710
|
+
observedDetails.push(`Scheduler status: ${observed.status}`);
|
|
711
|
+
}
|
|
712
|
+
if (observed?.cwdHealth) {
|
|
713
|
+
observedDetails.push(`Cwd: ${observed.cwdHealth.summary}`);
|
|
714
|
+
}
|
|
715
|
+
if (observed?.lastRunAt) {
|
|
716
|
+
observedDetails.push(`Last run: ${observed.lastRunAt}`);
|
|
717
|
+
} else if (observed) {
|
|
718
|
+
observedDetails.push("Last run metadata unavailable.");
|
|
719
|
+
}
|
|
720
|
+
if (runDisplay?.lastOutcome?.ts) {
|
|
721
|
+
observedDetails.push(`Newest run record: ${runDisplay.lastOutcome.ts}`);
|
|
722
|
+
}
|
|
723
|
+
if (observed?.lastRunSummary) {
|
|
724
|
+
observedDetails.push(`Latest summary: ${observed.lastRunSummary}`);
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
const status =
|
|
728
|
+
escalation?.status ??
|
|
729
|
+
runSignal?.status ??
|
|
730
|
+
/** @type {"HEALTHY" | "MISSING" | "DRIFTED"} */ (comparison.status);
|
|
731
|
+
|
|
732
|
+
return {
|
|
733
|
+
id: expected.automationId,
|
|
734
|
+
status,
|
|
735
|
+
summary: escalation
|
|
736
|
+
? escalation.summary
|
|
737
|
+
: composeAutomationSummary({
|
|
738
|
+
comparison,
|
|
739
|
+
runSignal,
|
|
740
|
+
}),
|
|
741
|
+
expectedCadence: expected.expectedCadence,
|
|
742
|
+
expectedCommand: expected.expectedCommand,
|
|
743
|
+
observed: observedDetails.join(" "),
|
|
744
|
+
runbook: runDisplay?.runbook,
|
|
745
|
+
lastOutcome: runDisplay?.lastOutcome,
|
|
746
|
+
outcomeHistory: runDisplay?.outcomeHistory,
|
|
747
|
+
olderRecordCount: runDisplay?.olderRecordCount,
|
|
748
|
+
remediation:
|
|
749
|
+
escalation?.remediation ??
|
|
750
|
+
runSignal?.remediation ??
|
|
751
|
+
comparison.remediation,
|
|
752
|
+
};
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
function composeAutomationSummary(input) {
|
|
756
|
+
const comparisonSummary = input.comparison.summary;
|
|
757
|
+
if (!input.runSignal) {
|
|
758
|
+
return comparisonSummary;
|
|
759
|
+
}
|
|
760
|
+
if (input.comparison.status === "HEALTHY") {
|
|
761
|
+
return input.runSignal.summary;
|
|
762
|
+
}
|
|
763
|
+
return `${input.runSignal.summary}; ${comparisonSummary}`;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
/**
|
|
767
|
+
* Milliseconds between scheduled runs, preferring what the scheduler actually
|
|
768
|
+
* reports over what the fleet expects.
|
|
769
|
+
*
|
|
770
|
+
* The observed RRULE wins because an automation re-cadenced in Codex is still
|
|
771
|
+
* a correctly running automation; measuring it against the expected cadence
|
|
772
|
+
* would manufacture findings out of an intentional change.
|
|
773
|
+
*
|
|
774
|
+
* @param {{
|
|
775
|
+
* readonly observed: { readonly observedRRule?: string | null }
|
|
776
|
+
* readonly expected: { readonly expectedCadence?: string }
|
|
777
|
+
* }} input - Observed automation entry and its expected-fleet counterpart.
|
|
778
|
+
* @returns {number | null} Interval in milliseconds, or `null` when neither
|
|
779
|
+
* side expresses a parseable cadence.
|
|
780
|
+
*/
|
|
781
|
+
function resolveObservedCadenceMs(input) {
|
|
782
|
+
return (
|
|
783
|
+
rruleToIntervalMs(input.observed.observedRRule) ??
|
|
784
|
+
cadenceLabelToIntervalMs(input.expected.expectedCadence) ??
|
|
785
|
+
null
|
|
786
|
+
);
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
function classifyAutomationRunSignal(input) {
|
|
790
|
+
const observed = input.observedAutomation;
|
|
791
|
+
if (!observed) {
|
|
792
|
+
return null;
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
if (observed.status && observed.status !== "ACTIVE") {
|
|
796
|
+
return {
|
|
797
|
+
status: "FAILING",
|
|
798
|
+
summary: `scheduler entry is ${observed.status.toLowerCase()}`,
|
|
799
|
+
remediation: "Resume or re-enable the automation in Codex.",
|
|
800
|
+
};
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
if (observed.cwdHealth && observed.cwdHealth.status !== "ok") {
|
|
804
|
+
return {
|
|
805
|
+
status: "FAILING",
|
|
806
|
+
summary: `scheduler cwd is invalid: ${observed.cwdHealth.summary}`,
|
|
807
|
+
remediation:
|
|
808
|
+
"Recreate the automation with `/lisa:setup-automations` so it uses a durable non-bare project checkout, then verify the cwd before the next run.",
|
|
809
|
+
};
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
if (observed.lastRunFailed) {
|
|
813
|
+
return {
|
|
814
|
+
status: "FAILING",
|
|
815
|
+
summary: "latest recorded run failed",
|
|
816
|
+
remediation:
|
|
817
|
+
"Inspect the latest automation run output and fix the failing job before re-running setup.",
|
|
818
|
+
};
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
if (!observed.lastRunAt) {
|
|
822
|
+
return null;
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
const cadenceMs = resolveObservedCadenceMs({
|
|
826
|
+
observed,
|
|
827
|
+
expected: input.expected,
|
|
828
|
+
});
|
|
829
|
+
if (!cadenceMs) {
|
|
830
|
+
return null;
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
const lastRunAt = Date.parse(observed.lastRunAt);
|
|
834
|
+
if (Number.isNaN(lastRunAt)) {
|
|
835
|
+
return null;
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
const staleAfterMs = cadenceMs * 3;
|
|
839
|
+
if (input.now.getTime() - lastRunAt > staleAfterMs) {
|
|
840
|
+
return {
|
|
841
|
+
status: "STALE",
|
|
842
|
+
summary: `last recorded run is stale for the expected cadence`,
|
|
843
|
+
remediation:
|
|
844
|
+
"Inspect why the automation has not run recently, then resume normal scheduling or recreate it with `/lisa:setup-automations`.",
|
|
845
|
+
};
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
return null;
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
async function inspectAutomationCwd(cwd, signal) {
|
|
852
|
+
signal?.throwIfAborted();
|
|
853
|
+
if (!cwd) {
|
|
854
|
+
return {
|
|
855
|
+
status: "missing",
|
|
856
|
+
summary: "no cwd configured",
|
|
857
|
+
};
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
const stat = await fs.stat(cwd).catch(error => {
|
|
861
|
+
if (error?.code === "ENOENT") {
|
|
862
|
+
return null;
|
|
863
|
+
}
|
|
864
|
+
throw error;
|
|
865
|
+
});
|
|
866
|
+
signal?.throwIfAborted();
|
|
867
|
+
|
|
868
|
+
if (!stat) {
|
|
869
|
+
return {
|
|
870
|
+
status: "missing",
|
|
871
|
+
summary: `${cwd} does not exist`,
|
|
872
|
+
};
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
if (!stat.isDirectory()) {
|
|
876
|
+
return {
|
|
877
|
+
status: "not_directory",
|
|
878
|
+
summary: `${cwd} is not a directory`,
|
|
879
|
+
};
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
try {
|
|
883
|
+
const { stdout } = await execGitWithRetry(
|
|
884
|
+
["-C", cwd, "rev-parse", "--is-inside-work-tree", "--is-bare-repository"],
|
|
885
|
+
{ timeout: 5000, signal }
|
|
886
|
+
);
|
|
887
|
+
const [insideWorkTree, bareRepository] = stdout.trim().split(/\r?\n/);
|
|
888
|
+
|
|
889
|
+
if (insideWorkTree !== "true") {
|
|
890
|
+
return {
|
|
891
|
+
status: "not_git_work_tree",
|
|
892
|
+
summary: `${cwd} is not inside a Git work tree`,
|
|
893
|
+
};
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
if (bareRepository === "true") {
|
|
897
|
+
return {
|
|
898
|
+
status: "bare_git_repository",
|
|
899
|
+
summary: `${cwd} is configured as a bare Git repository`,
|
|
900
|
+
};
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
return {
|
|
904
|
+
status: "ok",
|
|
905
|
+
summary: `${cwd} is a valid Git work tree`,
|
|
906
|
+
};
|
|
907
|
+
} catch (error) {
|
|
908
|
+
signal?.throwIfAborted();
|
|
909
|
+
return {
|
|
910
|
+
status: "git_error",
|
|
911
|
+
summary: `git could not inspect ${cwd}: ${String(error?.message ?? error)}`,
|
|
912
|
+
};
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
function resolveDefaultCodexAutomationsDir() {
|
|
917
|
+
return path.join(
|
|
918
|
+
process.env.CODEX_HOME ?? path.join(os.homedir(), ".codex"),
|
|
919
|
+
"automations"
|
|
920
|
+
);
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
function humanizeAutomationCadence(rrule) {
|
|
924
|
+
if (!rrule) {
|
|
925
|
+
return undefined;
|
|
926
|
+
}
|
|
927
|
+
if (rrule === "FREQ=HOURLY;INTERVAL=1") {
|
|
928
|
+
return "every 60 minutes";
|
|
929
|
+
}
|
|
930
|
+
if (rrule === "FREQ=MINUTELY;INTERVAL=10") {
|
|
931
|
+
return "every 10 minutes";
|
|
932
|
+
}
|
|
933
|
+
if (rrule === "FREQ=DAILY;INTERVAL=1") {
|
|
934
|
+
return "once a day";
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
const everyMinutes = rrule.match(/^FREQ=MINUTELY;INTERVAL=(\d+)$/);
|
|
938
|
+
if (everyMinutes?.[1]) {
|
|
939
|
+
return `every ${everyMinutes[1]} minutes`;
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
const everyHours = rrule.match(/^FREQ=HOURLY;INTERVAL=(\d+)$/);
|
|
943
|
+
if (everyHours?.[1]) {
|
|
944
|
+
return `every ${Number(everyHours[1]) * 60} minutes`;
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
const everyDays = rrule.match(/^FREQ=DAILY;INTERVAL=(\d+)$/);
|
|
948
|
+
if (everyDays?.[1]) {
|
|
949
|
+
return Number(everyDays[1]) === 1
|
|
950
|
+
? "once a day"
|
|
951
|
+
: `every ${everyDays[1]} days`;
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
const everyWeeks = rrule.match(/^FREQ=WEEKLY;INTERVAL=(\d+)$/);
|
|
955
|
+
if (everyWeeks?.[1]) {
|
|
956
|
+
return Number(everyWeeks[1]) === 1
|
|
957
|
+
? "once a week"
|
|
958
|
+
: `every ${everyWeeks[1]} weeks`;
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
return rrule;
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
function rruleToIntervalMs(rrule) {
|
|
965
|
+
if (!rrule) {
|
|
966
|
+
return null;
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
const minutely = rrule.match(/^FREQ=MINUTELY;INTERVAL=(\d+)$/);
|
|
970
|
+
if (minutely?.[1]) {
|
|
971
|
+
return Number(minutely[1]) * 60_000;
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
const hourly = rrule.match(/^FREQ=HOURLY;INTERVAL=(\d+)$/);
|
|
975
|
+
if (hourly?.[1]) {
|
|
976
|
+
return Number(hourly[1]) * 60 * 60_000;
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
const daily = rrule.match(/^FREQ=DAILY;INTERVAL=(\d+)$/);
|
|
980
|
+
if (daily?.[1]) {
|
|
981
|
+
return Number(daily[1]) * 24 * 60 * 60_000;
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
const weekly = rrule.match(/^FREQ=WEEKLY;INTERVAL=(\d+)$/);
|
|
985
|
+
if (weekly?.[1]) {
|
|
986
|
+
return Number(weekly[1]) * 7 * 24 * 60 * 60_000;
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
return null;
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
function cadenceLabelToIntervalMs(label) {
|
|
993
|
+
if (!label) {
|
|
994
|
+
return null;
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
const everyMinutes = label.match(/^every (\d+) minutes$/);
|
|
998
|
+
if (everyMinutes?.[1]) {
|
|
999
|
+
return Number(everyMinutes[1]) * 60_000;
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
if (label === "once a day") {
|
|
1003
|
+
return 24 * 60 * 60_000;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
if (label === "once a week") {
|
|
1007
|
+
return 7 * 24 * 60 * 60_000;
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
return null;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
function normalizeDate(value) {
|
|
1014
|
+
if (value instanceof Date) {
|
|
1015
|
+
return value;
|
|
1016
|
+
}
|
|
1017
|
+
if (typeof value === "string") {
|
|
1018
|
+
return new Date(value);
|
|
1019
|
+
}
|
|
1020
|
+
return new Date();
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
function stringOrUndefined(value) {
|
|
1024
|
+
return typeof value === "string" ? value : undefined;
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
function numberOrNull(value) {
|
|
1028
|
+
return typeof value === "number" ? value : null;
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
function parseAutomationToml(tomlContent) {
|
|
1032
|
+
return tomlContent
|
|
1033
|
+
.split(/\r?\n/)
|
|
1034
|
+
.map(line => line.trim())
|
|
1035
|
+
.filter(line => line && !line.startsWith("#"))
|
|
1036
|
+
.reduce((parsed, line) => {
|
|
1037
|
+
const separatorIndex = line.indexOf("=");
|
|
1038
|
+
if (separatorIndex === -1) {
|
|
1039
|
+
return parsed;
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
const key = line.slice(0, separatorIndex).trim();
|
|
1043
|
+
const rawValue = line.slice(separatorIndex + 1).trim();
|
|
1044
|
+
|
|
1045
|
+
return {
|
|
1046
|
+
...parsed,
|
|
1047
|
+
[key]: parseTomlValue(rawValue),
|
|
1048
|
+
};
|
|
1049
|
+
}, {});
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
function parseTomlValue(rawValue) {
|
|
1053
|
+
if (rawValue.startsWith('"') && rawValue.endsWith('"')) {
|
|
1054
|
+
return rawValue.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, "\\");
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
if (rawValue.startsWith("[") && rawValue.endsWith("]")) {
|
|
1058
|
+
const inner = rawValue.slice(1, -1).trim();
|
|
1059
|
+
if (!inner) {
|
|
1060
|
+
return [];
|
|
1061
|
+
}
|
|
1062
|
+
return inner
|
|
1063
|
+
.split(",")
|
|
1064
|
+
.map(value => parseTomlValue(value.trim()))
|
|
1065
|
+
.filter(value => value !== undefined);
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
if (/^-?\d+$/.test(rawValue)) {
|
|
1069
|
+
return Number(rawValue);
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
if (rawValue === "true") {
|
|
1073
|
+
return true;
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
if (rawValue === "false") {
|
|
1077
|
+
return false;
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
return rawValue;
|
|
1081
|
+
}
|