@codyswann/lisa 4.22.8 → 4.22.10
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/all/copy-overwrite/scripts/lib/process-tree-runner.mjs +127 -0
- package/all/copy-overwrite/scripts/lisa-floor-collisions.mjs +63 -8
- package/all/copy-overwrite/scripts/lisa-hooks/parity-safety-net.sh +36 -6
- package/all/copy-overwrite/scripts/lisa-postinstall.mjs +35 -13
- package/all/copy-overwrite/scripts/lisa-reconcile-policy.mjs +11 -3
- package/all/copy-overwrite/scripts/lisa-run-gates.mjs +41 -8
- package/all/copy-overwrite/scripts/lisa-schema-validate.mjs +2 -2
- package/all/copy-overwrite/scripts/lisa-work-item.mjs +2 -1
- package/cdk/package-lisa/package.lisa.json +1 -1
- package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.js +24 -0
- package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
- package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
- package/dist/core/nightly-e2e-guard-behavior-certificate.js.map +1 -1
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +61 -51
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/dist/opencode/plugin-templates/parity-safety-net.sh +36 -6
- package/nestjs/package-lisa/package.lisa.json +1 -1
- package/package.json +3 -3
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-atlassian-access/SKILL.md +10 -13
- package/plugins/lisa/.codex-plugin/skills/lisa-doctor/SKILL.md +4 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-drive-pr-to-merge/SKILL.md +29 -4
- package/plugins/lisa/.codex-plugin/skills/lisa-github-sync/SKILL.md +8 -3
- package/plugins/lisa/.codex-plugin/skills/lisa-jam-access/SKILL.md +7 -10
- package/plugins/lisa/.codex-plugin/skills/lisa-jira-journey/SKILL.md +5 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-jira-journey/scripts/parse-plan.py +36 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-jira-sync/SKILL.md +1 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-linear-access/SKILL.md +8 -12
- package/plugins/lisa/.codex-plugin/skills/lisa-linear-sync/SKILL.md +1 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-nightly-lower-code-complexity/SKILL.md +7 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-notion-access/SKILL.md +7 -10
- package/plugins/lisa/.codex-plugin/skills/lisa-posthog-access/SKILL.md +7 -10
- package/plugins/lisa/.codex-plugin/skills/lisa-repair-intake/SKILL.md +19 -3
- package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +10 -6
- package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/publish-aws-bootstrap.mjs +95 -44
- package/plugins/lisa/.codex-plugin/skills/lisa-sentry-access/SKILL.md +7 -10
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-atlassian/SKILL.md +7 -10
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-linear/SKILL.md +9 -12
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-notion/SKILL.md +7 -10
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-aws/SKILL.md +7 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/SKILL.md +6 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/assets/session-start.sh +19 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/assets/setup.sh +1 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +25 -4
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-workstation/scripts/bounded-child.mjs +9 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-workstation/scripts/workstation.mjs +29 -21
- package/plugins/lisa/.codex-plugin/skills/lisa-sonarcloud-access/SKILL.md +7 -10
- package/plugins/lisa/.codex-plugin/skills/lisa-tracker-sync/SKILL.md +1 -1
- package/plugins/lisa/hooks/parity-safety-net.sh +36 -6
- package/plugins/lisa/hooks/threshold-ratchet-families.mjs +31 -7
- package/plugins/lisa/rules/reference/base-rules.md +1 -1
- package/plugins/lisa/rules/reference/config-resolution.md +5 -14
- package/plugins/lisa/scripts/install-remote-agent-aws.mjs +5 -1
- package/plugins/lisa/scripts/rollup-blocker-classification.mjs +18 -3
- package/plugins/lisa/skills/lisa-atlassian-access/SKILL.md +10 -13
- package/plugins/lisa/skills/lisa-doctor/SKILL.md +4 -2
- package/plugins/lisa/skills/lisa-drive-pr-to-merge/SKILL.md +29 -4
- package/plugins/lisa/skills/lisa-github-sync/SKILL.md +8 -3
- package/plugins/lisa/skills/lisa-jam-access/SKILL.md +7 -10
- package/plugins/lisa/skills/lisa-jira-journey/SKILL.md +5 -0
- package/plugins/lisa/skills/lisa-jira-journey/scripts/parse-plan.py +36 -2
- package/plugins/lisa/skills/lisa-jira-sync/SKILL.md +1 -1
- package/plugins/lisa/skills/lisa-linear-access/SKILL.md +8 -12
- package/plugins/lisa/skills/lisa-linear-sync/SKILL.md +1 -1
- package/plugins/lisa/skills/lisa-nightly-lower-code-complexity/SKILL.md +7 -1
- package/plugins/lisa/skills/lisa-notion-access/SKILL.md +7 -10
- package/plugins/lisa/skills/lisa-posthog-access/SKILL.md +7 -10
- package/plugins/lisa/skills/lisa-repair-intake/SKILL.md +19 -3
- package/plugins/lisa/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +10 -6
- package/plugins/lisa/skills/lisa-secrets-access/scripts/publish-aws-bootstrap.mjs +95 -44
- package/plugins/lisa/skills/lisa-sentry-access/SKILL.md +7 -10
- package/plugins/lisa/skills/lisa-setup-atlassian/SKILL.md +7 -10
- package/plugins/lisa/skills/lisa-setup-linear/SKILL.md +9 -12
- package/plugins/lisa/skills/lisa-setup-notion/SKILL.md +7 -10
- package/plugins/lisa/skills/lisa-setup-remote-aws/SKILL.md +7 -2
- package/plugins/lisa/skills/lisa-setup-remote-env/SKILL.md +6 -1
- package/plugins/lisa/skills/lisa-setup-remote-env/assets/session-start.sh +19 -0
- package/plugins/lisa/skills/lisa-setup-remote-env/assets/setup.sh +1 -0
- package/plugins/lisa/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +25 -4
- package/plugins/lisa/skills/lisa-setup-workstation/scripts/bounded-child.mjs +9 -0
- package/plugins/lisa/skills/lisa-setup-workstation/scripts/workstation.mjs +29 -21
- package/plugins/lisa/skills/lisa-sonarcloud-access/SKILL.md +7 -10
- package/plugins/lisa/skills/lisa-tracker-sync/SKILL.md +1 -1
- package/plugins/lisa-agy/hooks/parity-safety-net.sh +36 -6
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/scripts/install-remote-agent-aws.mjs +5 -1
- package/plugins/lisa-agy/scripts/rollup-blocker-classification.mjs +18 -3
- package/plugins/lisa-agy/skills/lisa-atlassian-access/SKILL.md +10 -13
- package/plugins/lisa-agy/skills/lisa-doctor/SKILL.md +4 -2
- package/plugins/lisa-agy/skills/lisa-drive-pr-to-merge/SKILL.md +29 -4
- package/plugins/lisa-agy/skills/lisa-github-sync/SKILL.md +8 -3
- package/plugins/lisa-agy/skills/lisa-jam-access/SKILL.md +7 -10
- package/plugins/lisa-agy/skills/lisa-jira-journey/SKILL.md +5 -0
- package/plugins/lisa-agy/skills/lisa-jira-journey/scripts/parse-plan.py +36 -2
- package/plugins/lisa-agy/skills/lisa-jira-sync/SKILL.md +1 -1
- package/plugins/lisa-agy/skills/lisa-linear-access/SKILL.md +8 -12
- package/plugins/lisa-agy/skills/lisa-linear-sync/SKILL.md +1 -1
- package/plugins/lisa-agy/skills/lisa-nightly-lower-code-complexity/SKILL.md +7 -1
- package/plugins/lisa-agy/skills/lisa-notion-access/SKILL.md +7 -10
- package/plugins/lisa-agy/skills/lisa-posthog-access/SKILL.md +7 -10
- package/plugins/lisa-agy/skills/lisa-repair-intake/SKILL.md +19 -3
- package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +10 -6
- package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/publish-aws-bootstrap.mjs +95 -44
- package/plugins/lisa-agy/skills/lisa-sentry-access/SKILL.md +7 -10
- package/plugins/lisa-agy/skills/lisa-setup-atlassian/SKILL.md +7 -10
- package/plugins/lisa-agy/skills/lisa-setup-linear/SKILL.md +9 -12
- package/plugins/lisa-agy/skills/lisa-setup-notion/SKILL.md +7 -10
- package/plugins/lisa-agy/skills/lisa-setup-remote-aws/SKILL.md +7 -2
- package/plugins/lisa-agy/skills/lisa-setup-remote-env/SKILL.md +6 -1
- package/plugins/lisa-agy/skills/lisa-setup-remote-env/assets/session-start.sh +19 -0
- package/plugins/lisa-agy/skills/lisa-setup-remote-env/assets/setup.sh +1 -0
- package/plugins/lisa-agy/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +25 -4
- package/plugins/lisa-agy/skills/lisa-setup-workstation/scripts/bounded-child.mjs +9 -0
- package/plugins/lisa-agy/skills/lisa-setup-workstation/scripts/workstation.mjs +29 -21
- package/plugins/lisa-agy/skills/lisa-sonarcloud-access/SKILL.md +7 -10
- package/plugins/lisa-agy/skills/lisa-tracker-sync/SKILL.md +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-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/hooks/parity-safety-net.sh +36 -6
- package/plugins/lisa-copilot/hooks/threshold-ratchet-families.mjs +31 -7
- package/plugins/lisa-copilot/rules/reference/base-rules.md +1 -1
- package/plugins/lisa-copilot/rules/reference/config-resolution.md +5 -14
- package/plugins/lisa-copilot/scripts/install-remote-agent-aws.mjs +5 -1
- package/plugins/lisa-copilot/scripts/rollup-blocker-classification.mjs +18 -3
- package/plugins/lisa-copilot/skills/lisa-atlassian-access/SKILL.md +10 -13
- package/plugins/lisa-copilot/skills/lisa-doctor/SKILL.md +4 -2
- package/plugins/lisa-copilot/skills/lisa-drive-pr-to-merge/SKILL.md +29 -4
- package/plugins/lisa-copilot/skills/lisa-github-sync/SKILL.md +8 -3
- package/plugins/lisa-copilot/skills/lisa-jam-access/SKILL.md +7 -10
- package/plugins/lisa-copilot/skills/lisa-jira-journey/SKILL.md +5 -0
- package/plugins/lisa-copilot/skills/lisa-jira-journey/scripts/parse-plan.py +36 -2
- package/plugins/lisa-copilot/skills/lisa-jira-sync/SKILL.md +1 -1
- package/plugins/lisa-copilot/skills/lisa-linear-access/SKILL.md +8 -12
- package/plugins/lisa-copilot/skills/lisa-linear-sync/SKILL.md +1 -1
- package/plugins/lisa-copilot/skills/lisa-nightly-lower-code-complexity/SKILL.md +7 -1
- package/plugins/lisa-copilot/skills/lisa-notion-access/SKILL.md +7 -10
- package/plugins/lisa-copilot/skills/lisa-posthog-access/SKILL.md +7 -10
- package/plugins/lisa-copilot/skills/lisa-repair-intake/SKILL.md +19 -3
- package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +10 -6
- package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/publish-aws-bootstrap.mjs +95 -44
- package/plugins/lisa-copilot/skills/lisa-sentry-access/SKILL.md +7 -10
- package/plugins/lisa-copilot/skills/lisa-setup-atlassian/SKILL.md +7 -10
- package/plugins/lisa-copilot/skills/lisa-setup-linear/SKILL.md +9 -12
- package/plugins/lisa-copilot/skills/lisa-setup-notion/SKILL.md +7 -10
- package/plugins/lisa-copilot/skills/lisa-setup-remote-aws/SKILL.md +7 -2
- package/plugins/lisa-copilot/skills/lisa-setup-remote-env/SKILL.md +6 -1
- package/plugins/lisa-copilot/skills/lisa-setup-remote-env/assets/session-start.sh +19 -0
- package/plugins/lisa-copilot/skills/lisa-setup-remote-env/assets/setup.sh +1 -0
- package/plugins/lisa-copilot/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +25 -4
- package/plugins/lisa-copilot/skills/lisa-setup-workstation/scripts/bounded-child.mjs +9 -0
- package/plugins/lisa-copilot/skills/lisa-setup-workstation/scripts/workstation.mjs +29 -21
- package/plugins/lisa-copilot/skills/lisa-sonarcloud-access/SKILL.md +7 -10
- package/plugins/lisa-copilot/skills/lisa-tracker-sync/SKILL.md +1 -1
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/hooks/parity-safety-net.sh +36 -6
- package/plugins/lisa-cursor/hooks/threshold-ratchet-families.mjs +31 -7
- package/plugins/lisa-cursor/rules/base-rules-reference.mdc +1 -1
- package/plugins/lisa-cursor/rules/config-resolution-reference.mdc +5 -14
- package/plugins/lisa-cursor/scripts/install-remote-agent-aws.mjs +5 -1
- package/plugins/lisa-cursor/scripts/rollup-blocker-classification.mjs +18 -3
- package/plugins/lisa-cursor/skills/lisa-atlassian-access/SKILL.md +10 -13
- package/plugins/lisa-cursor/skills/lisa-doctor/SKILL.md +4 -2
- package/plugins/lisa-cursor/skills/lisa-drive-pr-to-merge/SKILL.md +29 -4
- package/plugins/lisa-cursor/skills/lisa-github-sync/SKILL.md +8 -3
- package/plugins/lisa-cursor/skills/lisa-jam-access/SKILL.md +7 -10
- package/plugins/lisa-cursor/skills/lisa-jira-journey/SKILL.md +5 -0
- package/plugins/lisa-cursor/skills/lisa-jira-journey/scripts/parse-plan.py +36 -2
- package/plugins/lisa-cursor/skills/lisa-jira-sync/SKILL.md +1 -1
- package/plugins/lisa-cursor/skills/lisa-linear-access/SKILL.md +8 -12
- package/plugins/lisa-cursor/skills/lisa-linear-sync/SKILL.md +1 -1
- package/plugins/lisa-cursor/skills/lisa-nightly-lower-code-complexity/SKILL.md +7 -1
- package/plugins/lisa-cursor/skills/lisa-notion-access/SKILL.md +7 -10
- package/plugins/lisa-cursor/skills/lisa-posthog-access/SKILL.md +7 -10
- package/plugins/lisa-cursor/skills/lisa-repair-intake/SKILL.md +19 -3
- package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +10 -6
- package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/publish-aws-bootstrap.mjs +95 -44
- package/plugins/lisa-cursor/skills/lisa-sentry-access/SKILL.md +7 -10
- package/plugins/lisa-cursor/skills/lisa-setup-atlassian/SKILL.md +7 -10
- package/plugins/lisa-cursor/skills/lisa-setup-linear/SKILL.md +9 -12
- package/plugins/lisa-cursor/skills/lisa-setup-notion/SKILL.md +7 -10
- package/plugins/lisa-cursor/skills/lisa-setup-remote-aws/SKILL.md +7 -2
- package/plugins/lisa-cursor/skills/lisa-setup-remote-env/SKILL.md +6 -1
- package/plugins/lisa-cursor/skills/lisa-setup-remote-env/assets/session-start.sh +19 -0
- package/plugins/lisa-cursor/skills/lisa-setup-remote-env/assets/setup.sh +1 -0
- package/plugins/lisa-cursor/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +25 -4
- package/plugins/lisa-cursor/skills/lisa-setup-workstation/scripts/bounded-child.mjs +9 -0
- package/plugins/lisa-cursor/skills/lisa-setup-workstation/scripts/workstation.mjs +29 -21
- package/plugins/lisa-cursor/skills/lisa-sonarcloud-access/SKILL.md +7 -10
- package/plugins/lisa-cursor/skills/lisa-tracker-sync/SKILL.md +1 -1
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/src/base/hooks/parity-safety-net.sh +36 -6
- package/plugins/src/base/hooks/threshold-ratchet-families.mjs +31 -7
- package/plugins/src/base/rules/reference/base-rules.md +1 -1
- package/plugins/src/base/rules/reference/config-resolution.md +5 -14
- package/plugins/src/base/scripts/install-remote-agent-aws.mjs +5 -1
- package/plugins/src/base/scripts/rollup-blocker-classification.mjs +18 -3
- package/plugins/src/base/skills/lisa-atlassian-access/SKILL.md +10 -13
- package/plugins/src/base/skills/lisa-doctor/SKILL.md +4 -2
- package/plugins/src/base/skills/lisa-drive-pr-to-merge/SKILL.md +29 -4
- package/plugins/src/base/skills/lisa-github-sync/SKILL.md +8 -3
- package/plugins/src/base/skills/lisa-jam-access/SKILL.md +7 -10
- package/plugins/src/base/skills/lisa-jira-journey/SKILL.md +5 -0
- package/plugins/src/base/skills/lisa-jira-journey/scripts/parse-plan.py +36 -2
- package/plugins/src/base/skills/lisa-jira-sync/SKILL.md +1 -1
- package/plugins/src/base/skills/lisa-linear-access/SKILL.md +8 -12
- package/plugins/src/base/skills/lisa-linear-sync/SKILL.md +1 -1
- package/plugins/src/base/skills/lisa-nightly-lower-code-complexity/SKILL.md +7 -1
- package/plugins/src/base/skills/lisa-notion-access/SKILL.md +7 -10
- package/plugins/src/base/skills/lisa-posthog-access/SKILL.md +7 -10
- package/plugins/src/base/skills/lisa-repair-intake/SKILL.md +19 -3
- package/plugins/src/base/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +10 -6
- package/plugins/src/base/skills/lisa-secrets-access/scripts/publish-aws-bootstrap.mjs +95 -44
- package/plugins/src/base/skills/lisa-sentry-access/SKILL.md +7 -10
- package/plugins/src/base/skills/lisa-setup-atlassian/SKILL.md +7 -10
- package/plugins/src/base/skills/lisa-setup-linear/SKILL.md +9 -12
- package/plugins/src/base/skills/lisa-setup-notion/SKILL.md +7 -10
- package/plugins/src/base/skills/lisa-setup-remote-aws/SKILL.md +7 -2
- package/plugins/src/base/skills/lisa-setup-remote-env/SKILL.md +6 -1
- package/plugins/src/base/skills/lisa-setup-remote-env/assets/session-start.sh +19 -0
- package/plugins/src/base/skills/lisa-setup-remote-env/assets/setup.sh +1 -0
- package/plugins/src/base/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +25 -4
- package/plugins/src/base/skills/lisa-setup-workstation/scripts/bounded-child.mjs +9 -0
- package/plugins/src/base/skills/lisa-setup-workstation/scripts/workstation.mjs +29 -21
- package/plugins/src/base/skills/lisa-sonarcloud-access/SKILL.md +7 -10
- package/plugins/src/base/skills/lisa-tracker-sync/SKILL.md +1 -1
- package/rails/copy-overwrite/scripts/threshold-ratchet-families.mjs +31 -7
- package/scripts/lisa-remote-env/session-start.sh +19 -0
- package/scripts/lisa-remote-env/setup.sh +1 -0
- package/scripts/two-channel-couplings.json +1 -1
- package/typescript/copy-contents/.husky/pre-push +1 -1
- package/typescript/copy-overwrite/scripts/threshold-ratchet-families.mjs +31 -7
- package/typescript/package-lisa/package.lisa.json +1 -1
|
@@ -92,11 +92,11 @@ export const FAMILIES = [
|
|
|
92
92
|
* Unknown keys stay unwatched until their direction is explicit here.
|
|
93
93
|
* @type {Readonly<Record<string, "min"|"max">>}
|
|
94
94
|
*/
|
|
95
|
-
export const LIGHTHOUSE_ASSERTION_DIRECTIONS = {
|
|
95
|
+
export const LIGHTHOUSE_ASSERTION_DIRECTIONS = Object.freeze({
|
|
96
96
|
minScore: "min",
|
|
97
97
|
maxNumericValue: "max",
|
|
98
98
|
maxLength: "max",
|
|
99
|
-
};
|
|
99
|
+
});
|
|
100
100
|
|
|
101
101
|
/**
|
|
102
102
|
* Extract numeric Lighthouse assertions with a direction chosen per key.
|
|
@@ -109,10 +109,22 @@ export const LIGHTHOUSE_ASSERTION_DIRECTIONS = {
|
|
|
109
109
|
*/
|
|
110
110
|
export function extractLighthouseAssertions(conf) {
|
|
111
111
|
const out = new Map();
|
|
112
|
-
const
|
|
112
|
+
const root =
|
|
113
113
|
conf && typeof conf === "object" && !Array.isArray(conf)
|
|
114
|
-
? /** @type {Record<string, unknown>} */ (conf)
|
|
114
|
+
? /** @type {Record<string, unknown>} */ (conf)
|
|
115
115
|
: undefined;
|
|
116
|
+
const ci =
|
|
117
|
+
root?.ci && typeof root.ci === "object" && !Array.isArray(root.ci)
|
|
118
|
+
? /** @type {Record<string, unknown>} */ (root.ci)
|
|
119
|
+
: undefined;
|
|
120
|
+
const assert =
|
|
121
|
+
ci?.assert && typeof ci.assert === "object" && !Array.isArray(ci.assert)
|
|
122
|
+
? /** @type {Record<string, unknown>} */ (ci.assert)
|
|
123
|
+
: undefined;
|
|
124
|
+
// Lighthouse CI's canonical shape is `ci.assert.assertions`. Keep the
|
|
125
|
+
// historical top-level shape as a compatibility lane for already-generated
|
|
126
|
+
// project configs, but never merge the two into an ambiguous hybrid.
|
|
127
|
+
const assertions = assert?.assertions ?? root?.assertions;
|
|
116
128
|
if (
|
|
117
129
|
!assertions ||
|
|
118
130
|
typeof assertions !== "object" ||
|
|
@@ -121,9 +133,21 @@ export function extractLighthouseAssertions(conf) {
|
|
|
121
133
|
return out;
|
|
122
134
|
}
|
|
123
135
|
for (const [audit, spec] of Object.entries(assertions)) {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
136
|
+
const options =
|
|
137
|
+
Array.isArray(spec) &&
|
|
138
|
+
spec.length >= 2 &&
|
|
139
|
+
spec[1] &&
|
|
140
|
+
typeof spec[1] === "object" &&
|
|
141
|
+
!Array.isArray(spec[1])
|
|
142
|
+
? /** @type {Record<string, unknown>} */ (spec[1])
|
|
143
|
+
: spec && typeof spec === "object" && !Array.isArray(spec)
|
|
144
|
+
? /** @type {Record<string, unknown>} */ (spec)
|
|
145
|
+
: undefined;
|
|
146
|
+
if (!options) continue;
|
|
147
|
+
for (const [key, value] of Object.entries(options)) {
|
|
148
|
+
const direction = Object.hasOwn(LIGHTHOUSE_ASSERTION_DIRECTIONS, key)
|
|
149
|
+
? LIGHTHOUSE_ASSERTION_DIRECTIONS[key]
|
|
150
|
+
: undefined;
|
|
127
151
|
if (direction && typeof value === "number" && Number.isFinite(value)) {
|
|
128
152
|
out.set(`${audit}.${key}`, { value, direction });
|
|
129
153
|
}
|
|
@@ -70,7 +70,7 @@ Testing Discipline:
|
|
|
70
70
|
JIRA Discipline:
|
|
71
71
|
- If working on a JIRA issue, make sure the branch you're working on references and is added to the JIRA issue.
|
|
72
72
|
- If working on a JIRA issue, update the issue as you work through it. For example, if working on a Bug Triage, update the issue with your questions/feedback/suggestions.
|
|
73
|
-
- When reading a JIRA issue, always read ALL comments on the ticket — not just the description. Comments contain critical context: stakeholder decisions, scope changes, blockers, triage findings from other repos, and implementation notes. Use the Atlassian MCP or first resolve the project root from `$CLAUDE_PROJECT_DIR` or `git rev-parse --show-toplevel
|
|
73
|
+
- When reading a JIRA issue, always read ALL comments on the ticket — not just the description. Comments contain critical context: stakeholder decisions, scope changes, blockers, triage findings from other repos, and implementation notes. Use the Atlassian MCP or first resolve the project root from `$CLAUDE_PROJECT_DIR` or `git rev-parse --show-toplevel`. When `$PROJECT_ROOT/.lisa/jira-cli/.config.yml` exists, run both `jira --config "$PROJECT_ROOT/.lisa/jira-cli/.config.yml" issue view <TICKET_ID>` and `jira --config "$PROJECT_ROOT/.lisa/jira-cli/.config.yml" issue comment list <TICKET_ID>`; the dedicated comment-list command returns the complete comment collection instead of a fixed recent-comment window. If that project config is absent, omit `--config` from both commands to use the machine's own `~/.config/.jira/.config.yml`.
|
|
74
74
|
- When requesting clarification on a JIRA issue, post the question as a comment using ADF (Atlassian Document Format) and @mention the Reporter so they receive a notification.
|
|
75
75
|
- When creating JIRA tickets, establish issue link relationships (e.g. "is blocked by", "blocks", "relates to", "is duplicated by") between tickets that have dependencies or logical connections. Do not leave related tickets unlinked. Relationship discovery is mandatory on every create and update — search BOTH the local git history (`git log --all --grep=<keyword>`, `git log -- <path>`) AND Jira (JQL by component, keyword, label, epic siblings) before declaring "no related work." Record the searches you ran and their outcomes in the description (or a comment) so a reviewer can see the search was real.
|
|
76
76
|
- Ticket scope by type: Bug, Task, and Sub-task tickets MUST be single-repo (one work unit, one repo). Epic, Spike, and Story tickets MAY span multiple repos. If a Bug/Task/Sub-task crosses repos, split it per the `repo-scope-split` rule — at PRD-decomposition time via `task-decomposition` step 1.5 (parent Story + per-repo children); at work-time (an existing ticket an agent is about to implement) via the work-time split procedure (narrow the original to one repo, spin off a sibling per additional repo cloning its metadata, link the producer→consumer dependency, then proceed). A cross-repo work unit is a decomposition error the agent fixes by splitting, not a reason to bounce the ticket to the reporter.
|
|
@@ -899,19 +899,10 @@ read_notion_token() {
|
|
|
899
899
|
# and the surface ladder. An agent following this reference must try it before
|
|
900
900
|
# any keychain — a second reader is how one credential ends up in two places.
|
|
901
901
|
#
|
|
902
|
-
#
|
|
903
|
-
#
|
|
904
|
-
#
|
|
905
|
-
|
|
906
|
-
# plugin itself is installed. Without one, a consumer repository that vendors
|
|
907
|
-
# none of the leading paths never reaches a resolver at all — and an agent
|
|
908
|
-
# copying a two-rung ladder out of THIS reference reproduces that.
|
|
909
|
-
local candidates=(
|
|
910
|
-
.claude/skills/lisa-secrets-access/scripts/resolve-secret.mjs
|
|
911
|
-
.agents/skills/lisa-secrets-access/scripts/resolve-secret.mjs
|
|
912
|
-
.opencode/skills/lisa/lisa-secrets-access/scripts/resolve-secret.mjs
|
|
913
|
-
.codex/skills/lisa/lisa-secrets-access/scripts/resolve-secret.mjs
|
|
914
|
-
)
|
|
902
|
+
# Resolver scripts are executable code, so a familiar checkout-local path is
|
|
903
|
+
# not provenance. Use only machine-managed plugin roots and the installed
|
|
904
|
+
# package; never execute repository-controlled candidates from this ladder.
|
|
905
|
+
local candidates=()
|
|
915
906
|
if [ -n "${CLAUDE_PLUGIN_ROOT:-}" ]; then
|
|
916
907
|
candidates+=("$CLAUDE_PLUGIN_ROOT/skills/lisa-secrets-access/scripts/resolve-secret.mjs")
|
|
917
908
|
fi
|
|
@@ -930,7 +921,7 @@ read_notion_token() {
|
|
|
930
921
|
local via_lisa
|
|
931
922
|
via_lisa=$(node "$resolver" get NOTION_API_TOKEN 2>/dev/null) \
|
|
932
923
|
&& [ -n "$via_lisa" ] && { echo "$via_lisa"; return; }
|
|
933
|
-
|
|
924
|
+
# Empty/error means this substrate had no answer; try the next trusted one.
|
|
934
925
|
fi
|
|
935
926
|
done
|
|
936
927
|
# Legacy fallback: the OS keychain written by the guided setup flow, for
|
|
@@ -329,12 +329,16 @@ the complete bundle from the shared account. Do not extract or distribute its
|
|
|
329
329
|
individual access-key fields:
|
|
330
330
|
|
|
331
331
|
\`\`\`bash
|
|
332
|
-
aws
|
|
332
|
+
aws secretsmanager get-secret-value \\
|
|
333
333
|
--secret-id ${secretName} \\
|
|
334
334
|
--query SecretString \\
|
|
335
335
|
--output text
|
|
336
336
|
\`\`\`
|
|
337
337
|
|
|
338
|
+
This uses the ambient AWS identity. Add \`--profile <source-profile>\` only when
|
|
339
|
+
this project requires a named source profile to read the emission; \`shared\` is
|
|
340
|
+
not an implicit requirement.
|
|
341
|
+
|
|
338
342
|
Store that exact output as the masked secret \`LISA_AWS_BOOTSTRAP_JSON\` on each
|
|
339
343
|
remote-agent platform. Run the setup command and require its live
|
|
340
344
|
\`sts:GetCallerIdentity\` check to pass before considering the platform ready.
|
|
@@ -293,6 +293,8 @@ function collectHolds(children, context, path, seen, tally) {
|
|
|
293
293
|
* container?: { ref?: unknown, type?: unknown }
|
|
294
294
|
* readError?: unknown
|
|
295
295
|
* children?: unknown
|
|
296
|
+
* renderedState?: unknown
|
|
297
|
+
* childTally?: unknown
|
|
296
298
|
* blockedStates?: unknown
|
|
297
299
|
* markerNames?: { specDefect?: unknown, humanNeeded?: unknown }
|
|
298
300
|
* }} input
|
|
@@ -339,6 +341,10 @@ export function classifyRollupBlockers(input = {}) {
|
|
|
339
341
|
blockers.filter(blocker => blocker.class === name),
|
|
340
342
|
]).filter(([, group]) => group.length > 0)
|
|
341
343
|
);
|
|
344
|
+
const renderedState = trimmedString(input.renderedState);
|
|
345
|
+
const childTally =
|
|
346
|
+
trimmedString(input.childTally) ||
|
|
347
|
+
`examined=${tally.examined}, held=${blockers.length}, unreadable=${tally.unexaminable.length}`;
|
|
342
348
|
|
|
343
349
|
return {
|
|
344
350
|
ok: true,
|
|
@@ -348,6 +354,8 @@ export function classifyRollupBlockers(input = {}) {
|
|
|
348
354
|
blockers,
|
|
349
355
|
byClass,
|
|
350
356
|
unexaminable: tally.unexaminable,
|
|
357
|
+
renderedState,
|
|
358
|
+
childTally,
|
|
351
359
|
};
|
|
352
360
|
}
|
|
353
361
|
|
|
@@ -433,8 +441,8 @@ export function renderRollupBlockerReport(result) {
|
|
|
433
441
|
}
|
|
434
442
|
|
|
435
443
|
/**
|
|
436
|
-
* A stable identity for a rollup
|
|
437
|
-
* and its class, sorted.
|
|
444
|
+
* A stable identity for a rollup note: the rendered lifecycle state, child
|
|
445
|
+
* tally, container, and every held item plus its class, sorted.
|
|
438
446
|
*
|
|
439
447
|
* This is what lets a repeat cycle stay quiet. 32 identical hold comments over
|
|
440
448
|
* six weeks was the same verdict restated on a schedule; comparing this string
|
|
@@ -451,7 +459,14 @@ export function rollupBlockerFingerprint(result) {
|
|
|
451
459
|
.map(blocker => `${blocker.ref}:${blocker.class}`)
|
|
452
460
|
.sort((left, right) => left.localeCompare(right));
|
|
453
461
|
|
|
454
|
-
return
|
|
462
|
+
return [
|
|
463
|
+
`container=${result.container.ref}`,
|
|
464
|
+
`verdict=${result.verdict}`,
|
|
465
|
+
`rendered=${JSON.stringify(trimmedString(result.renderedState))}`,
|
|
466
|
+
`tally=${JSON.stringify(trimmedString(result.childTally))}`,
|
|
467
|
+
`examined=${result.examined}`,
|
|
468
|
+
`holds=${pairs.join(",")}`,
|
|
469
|
+
].join(";");
|
|
455
470
|
}
|
|
456
471
|
|
|
457
472
|
/**
|
|
@@ -57,9 +57,9 @@ read_atlassian_token() {
|
|
|
57
57
|
# OS keychain here — a second reader is how the same credential ends up living
|
|
58
58
|
# in two places and drifting.
|
|
59
59
|
#
|
|
60
|
-
# Ordered
|
|
61
|
-
#
|
|
62
|
-
#
|
|
60
|
+
# Ordered across trusted machine-managed substrates, ending at the installed
|
|
61
|
+
# package. Checkout-local paths are deliberately absent: a familiar generated
|
|
62
|
+
# destination is still repository-controlled executable code. The plugin
|
|
63
63
|
# rungs are the floor: `resolve-secret.mjs` ships beside this skill, so a rung
|
|
64
64
|
# pointing at it is reachable from anywhere the plugin itself is installed.
|
|
65
65
|
# Without one, a consumer repository that vendors none of the leading paths
|
|
@@ -68,12 +68,9 @@ read_atlassian_token() {
|
|
|
68
68
|
# lookups. This LADDER is identical in every skill that resolves a credential
|
|
69
69
|
# and `credential-resolver-ladder` fails if any copy diverges. Only what
|
|
70
70
|
# happens AFTER the ladder may differ between them.
|
|
71
|
-
local
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
.opencode/skills/lisa/lisa-secrets-access/scripts/resolve-secret.mjs
|
|
75
|
-
.codex/skills/lisa/lisa-secrets-access/scripts/resolve-secret.mjs
|
|
76
|
-
)
|
|
71
|
+
# Executable resolvers are a code boundary. Checkout-local copies are mutable
|
|
72
|
+
# repository content, so use only machine-managed plugin/package locations.
|
|
73
|
+
local candidates=()
|
|
77
74
|
if [ -n "${CLAUDE_PLUGIN_ROOT:-}" ]; then
|
|
78
75
|
candidates+=("$CLAUDE_PLUGIN_ROOT/skills/lisa-secrets-access/scripts/resolve-secret.mjs")
|
|
79
76
|
fi
|
|
@@ -92,7 +89,7 @@ read_atlassian_token() {
|
|
|
92
89
|
local via_lisa
|
|
93
90
|
via_lisa=$(node "$resolver" get ATLASSIAN_API_TOKEN 2>/dev/null) \
|
|
94
91
|
&& [ -n "$via_lisa" ] && { echo "$via_lisa"; return; }
|
|
95
|
-
|
|
92
|
+
# Empty/error means this substrate had no answer; try the next trusted one.
|
|
96
93
|
fi
|
|
97
94
|
done
|
|
98
95
|
# Legacy fallback: the OS keychain written by the guided /lisa:setup:atlassian
|
|
@@ -152,7 +149,7 @@ public static class LisaCred {
|
|
|
152
149
|
echo "Error: could not resolve ATLASSIAN_API_TOKEN through lisa-secrets-access or the legacy keychain." >&2
|
|
153
150
|
echo "Tried, in order (relative paths are from $PWD):" >&2
|
|
154
151
|
printf ' %s\n' "${tried[@]}" >&2
|
|
155
|
-
echo " <OS keychain> service=lisa-atlassian account
|
|
152
|
+
echo " <OS keychain> service=lisa-atlassian account=<configured>" >&2
|
|
156
153
|
return 1
|
|
157
154
|
}
|
|
158
155
|
TOKEN=$(read_atlassian_token "$EMAIL")
|
|
@@ -288,7 +285,7 @@ if [ -n "$site" ] && [ "$current_site" != "$site" ]; then
|
|
|
288
285
|
fi
|
|
289
286
|
|
|
290
287
|
if [ -n "$email" ] && [ -n "$current_email" ] && [ "$current_email" != "$email" ]; then
|
|
291
|
-
echo "Error: acli active account
|
|
288
|
+
echo "Error: acli active account does not match the configured Atlassian account. Run /lisa:setup:atlassian to add or repair the matching profile." >&2
|
|
292
289
|
exit 1
|
|
293
290
|
fi
|
|
294
291
|
```
|
|
@@ -310,7 +307,7 @@ if [ -z "$me_email" ]; then
|
|
|
310
307
|
exit 1
|
|
311
308
|
fi
|
|
312
309
|
if [ "$me_email" != "$email" ]; then
|
|
313
|
-
echo "Error: ATLASSIAN_API_TOKEN
|
|
310
|
+
echo "Error: ATLASSIAN_API_TOKEN identity does not match the configured Atlassian account. Multi-account misconfiguration; re-run /lisa:setup:atlassian." >&2
|
|
314
311
|
exit 1
|
|
315
312
|
fi
|
|
316
313
|
```
|
|
@@ -480,8 +480,8 @@ against both enforcing surfaces on paths a machine already takes:
|
|
|
480
480
|
| the shipped ruleset template a repository is provisioned from | `lisa doctor` (one operator-readable line) and `lisa doctor --json` → `declarationDrift.templates` | no |
|
|
481
481
|
| the live branch-protection ruleset | `lisa doctor --json` → `declarationDrift.live`, and the `github.declared-checks` check in `lisa health` | yes |
|
|
482
482
|
|
|
483
|
-
Both report one verdict per required context, and the vocabulary is
|
|
484
|
-
matched/unmatched, because
|
|
483
|
+
Both report one verdict per required context, and the vocabulary is seven values rather than
|
|
484
|
+
matched/unmatched, because the mismatches and an unreadable surface need different actions:
|
|
485
485
|
|
|
486
486
|
- `matched` — declared `required`, and the surface requires it.
|
|
487
487
|
- `declared-not-enforced` — the settings file says it must pass and nothing requires it. The
|
|
@@ -495,6 +495,8 @@ matched/unmatched, because four of the mismatches need four different actions:
|
|
|
495
495
|
- `enforced-not-lisa-owned` — protection requires it and no registry gate produces it. Third-party
|
|
496
496
|
checks are required by construction and declared by nobody; this bucket exists so they can be told
|
|
497
497
|
apart from a Lisa gate that fell out of the settings file, never so they can be removed.
|
|
498
|
+
- `unproven` — the surface could not be read, so no enforcement comparison was made. It is never a
|
|
499
|
+
match and never drift; the operator fixes access/availability and reruns the observation.
|
|
498
500
|
|
|
499
501
|
`enforced-declared-off` and `declared-not-enforced` fail the health check; the two gaps warn. No
|
|
500
502
|
remedy in that vocabulary removes a required context — the type has no such member, so the
|
|
@@ -343,9 +343,18 @@ auto-merge armed (section 1); when it returns, re-read `headRefOid` and reset
|
|
|
343
343
|
|
|
344
344
|
**Merging past a rate-limited CodeRabbit is permitted — but ONLY when CodeRabbit
|
|
345
345
|
is the sole gate still blocking the merge.** When the CodeRabbit context reports
|
|
346
|
-
`Review rate limited`
|
|
347
|
-
|
|
348
|
-
|
|
346
|
+
`Review rate limited` and it is the *only* thing standing between the PR and
|
|
347
|
+
`MERGED`, do not wait it out. Prove that vendor-cap signal from the live check
|
|
348
|
+
description; `statusCheckRollup` does not carry enough detail, so read it with:
|
|
349
|
+
|
|
350
|
+
```bash
|
|
351
|
+
gh pr checks <pr> --json name,state,description,bucket \
|
|
352
|
+
--jq '.[] | select(.name == "CodeRabbit")'
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
A merely pending or queued CodeRabbit check is not proof of a vendor cap and
|
|
356
|
+
must keep polling. Once that signal is explicit, and with `auto_merge=true`, the
|
|
357
|
+
PR already has auto-merge enabled (section 1), so
|
|
349
358
|
leave the latch armed and merge directly with `gh pr merge <pr> --<merge_method>`
|
|
350
359
|
(pass `--admin` only if branch protection lists the rate-limited context as
|
|
351
360
|
required and refuses the plain merge). "Sole gate" means every one of these is
|
|
@@ -355,7 +364,15 @@ from memory:
|
|
|
355
364
|
- every other required check in `statusCheckRollup` is green (no FAILURE, no
|
|
356
365
|
other PENDING);
|
|
357
366
|
- zero unresolved review threads (human or bot);
|
|
358
|
-
-
|
|
367
|
+
- the repository's human-approval requirement is demonstrably satisfied at the
|
|
368
|
+
current head: read the live branch/ruleset requirement, and when it requires
|
|
369
|
+
one or more approvals require `reviewDecision == APPROVED` plus the current
|
|
370
|
+
**effective** non-dismissed approval count. Compute effective reviews from the
|
|
371
|
+
latest non-dismissed review per reviewer, ordered by `submitted_at` then id;
|
|
372
|
+
an older approval from a reviewer never satisfies a later `CHANGES_REQUESTED`
|
|
373
|
+
from that reviewer. If the required count is zero, record that live
|
|
374
|
+
policy result. `REVIEW_REQUIRED`, `CHANGES_REQUESTED`, and `null` never stand
|
|
375
|
+
in for this proof before an admin merge;
|
|
359
376
|
- `mergeable == MERGEABLE` and `mergeStateStatus` is not `BEHIND`/`DIRTY`;
|
|
360
377
|
- no pending auto-fix PR into this branch (step f).
|
|
361
378
|
|
|
@@ -380,6 +397,14 @@ Some org rulesets allow 0 approvals yet a bot `CHANGES_REQUESTED` still blocks
|
|
|
380
397
|
auto-merge — dismissing the stale review after resolving all threads is what
|
|
381
398
|
unblocks it.
|
|
382
399
|
|
|
400
|
+
When reading review history, derive the current review set rather than counting
|
|
401
|
+
the whole array. One reproducible REST shape is:
|
|
402
|
+
|
|
403
|
+
```bash
|
|
404
|
+
gh api --paginate repos/<owner>/<repo>/pulls/<pr>/reviews --slurp \
|
|
405
|
+
--jq 'add | map(select(.state != "DISMISSED")) | sort_by(.submitted_at, .id) | reduce .[] as $review ({}; .[$review.user.login] = $review) | [.[]]'
|
|
406
|
+
```
|
|
407
|
+
|
|
383
408
|
### f. Pending auto-fix PR into this branch
|
|
384
409
|
If an open PR from `claude-auto-fix-<headRefName>` targets this PR's head
|
|
385
410
|
branch (the CI auto-fix workflow engaged before this session took the lease),
|
|
@@ -113,10 +113,15 @@ If the `subIssues` field is unavailable (older GHES), fall back to body parentag
|
|
|
113
113
|
- **Blocked dominates — and the rollup must say which child and which kind** — a single blocked child surfaces `status:blocked` on the parent even while siblings progress, so a human sees the parent needs attention. `status:blocked` alone is a single bit and cannot tell a child waiting on an external event from one whose acceptance criteria are unbuildable; the second never clears on its own. Run the shared classifier over the resolved child graph before writing the label or the comment:
|
|
114
114
|
|
|
115
115
|
```bash
|
|
116
|
-
|
|
116
|
+
CLASSIFIER_ROOT="${CLAUDE_PLUGIN_ROOT:-${PLUGIN_ROOT:-plugins/lisa}}"
|
|
117
|
+
node "${CLASSIFIER_ROOT}/scripts/rollup-blocker-classification.mjs" --input=<graph.json>
|
|
117
118
|
```
|
|
118
119
|
|
|
119
|
-
|
|
120
|
+
The current-directory `plugins/lisa` fallback is for a Lisa checkout where no
|
|
121
|
+
plugin-root variable is injected; it must be tried before declaring the shared
|
|
122
|
+
classifier absent.
|
|
123
|
+
|
|
124
|
+
Its report names, per class, the blocking leaf, the path to it (`#1495 -> #1515 -> #1547`) and **who must act** — that text goes in the rollup comment verbatim. It exits non-zero when it classified nothing (unreadable graph, no children, no readable child): that is a strict **no-write** result. Do not change a label and do not post/update a rollup comment; report the classifier failure to the caller. Never fall through to "no blocked children", infer a class from prose, or apply the `spec_defect` marker from a flow — see `leaf-only-lifecycle` → **Classifying a hold**.
|
|
120
125
|
- **Least-advanced env wins** — the parent reaches an env only when every required child has reached at least that env; it never sits ahead of its laggard child. Native closure (`gh issue close --reason completed`) fires only when the resolved env is the production `status:done`, never at `status:on-dev`/`status:on-stg`.
|
|
121
126
|
- **"Required" children only** — a child labelled won't-do / optional does not hold the parent open; only leaves that must ship count toward the env-rollup check.
|
|
122
127
|
- **Recursive** — a parent reaches an env only when its children have all reached at least that env; an Epic reaches it only when its Stories have themselves rolled up to it. Evaluate bottom-up.
|
|
@@ -131,7 +136,7 @@ gh issue edit <parent-number> --repo <org>/<repo> \
|
|
|
131
136
|
--remove-label "<current status:*>" --add-label "<derived status:*>"
|
|
132
137
|
```
|
|
133
138
|
|
|
134
|
-
**Safe default.** If rollup cannot be applied automatically (e.g. ambiguous required-set
|
|
139
|
+
**Safe default.** If a successfully-read rollup cannot be applied automatically (e.g. ambiguous required-set or a derived terminal that the env logic cannot resolve), this skill does **not** guess — it posts the derived suggestion as a comment and leaves the parent's label untouched. A classifier/read failure is stricter: it writes neither label nor comment. No unsafe transition is ever made.
|
|
135
140
|
|
|
136
141
|
## Important Notes
|
|
137
142
|
|
|
@@ -48,9 +48,9 @@ export PATH="$HOME/.local/bin:$PATH"
|
|
|
48
48
|
read_jam_pat() {
|
|
49
49
|
[ -n "${JAM_PAT:-}" ] && { echo "$JAM_PAT"; return; }
|
|
50
50
|
#
|
|
51
|
-
# Ordered
|
|
52
|
-
#
|
|
53
|
-
#
|
|
51
|
+
# Ordered across trusted machine-managed substrates, ending at the installed
|
|
52
|
+
# package. Checkout-local paths are deliberately absent: a familiar generated
|
|
53
|
+
# destination is still repository-controlled executable code. The plugin
|
|
54
54
|
# rungs are the floor: `resolve-secret.mjs` ships beside this skill, so a rung
|
|
55
55
|
# pointing at it is reachable from anywhere the plugin itself is installed.
|
|
56
56
|
# Without one, a consumer repository that vendors none of the leading paths
|
|
@@ -59,12 +59,9 @@ read_jam_pat() {
|
|
|
59
59
|
# lookups. This LADDER is identical in every skill that resolves a credential
|
|
60
60
|
# and `credential-resolver-ladder` fails if any copy diverges. Only what
|
|
61
61
|
# happens AFTER the ladder may differ between them.
|
|
62
|
-
local
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
.opencode/skills/lisa/lisa-secrets-access/scripts/resolve-secret.mjs
|
|
66
|
-
.codex/skills/lisa/lisa-secrets-access/scripts/resolve-secret.mjs
|
|
67
|
-
)
|
|
62
|
+
# Execute only machine-managed plugin/package resolvers. Checkout-local
|
|
63
|
+
# candidates are repository-controlled code, not trusted merely by path.
|
|
64
|
+
local candidates=()
|
|
68
65
|
if [ -n "${CLAUDE_PLUGIN_ROOT:-}" ]; then
|
|
69
66
|
candidates+=("$CLAUDE_PLUGIN_ROOT/skills/lisa-secrets-access/scripts/resolve-secret.mjs")
|
|
70
67
|
fi
|
|
@@ -83,7 +80,7 @@ read_jam_pat() {
|
|
|
83
80
|
local via_lisa
|
|
84
81
|
via_lisa=$(node "$resolver" get JAM_PAT 2>/dev/null) \
|
|
85
82
|
&& [ -n "$via_lisa" ] && { echo "$via_lisa"; return; }
|
|
86
|
-
|
|
83
|
+
# Empty/error means this substrate had no answer; try the next trusted one.
|
|
87
84
|
fi
|
|
88
85
|
done
|
|
89
86
|
# Name every path. A bare `return 1` sends the next reader hunting for a
|
|
@@ -35,6 +35,11 @@ Run the parser script to extract the Validation Journey from the JIRA ticket des
|
|
|
35
35
|
python3 .claude/skills/jira-journey/scripts/parse-plan.py <TICKET_ID>
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
+
The parser resolves Jira configuration from the checkout first: it searches
|
|
39
|
+
`$CLAUDE_PROJECT_DIR/.lisa/jira-cli/.config.yml`, then the current directory and
|
|
40
|
+
its parents, and only then falls back to `~/.config/.jira/.config.yml`. Do not
|
|
41
|
+
copy project settings into the home-level file just to make this step work.
|
|
42
|
+
|
|
38
43
|
The script outputs JSON with: `ticket`, `prerequisites`, `steps`, `viewports`, `assertions`.
|
|
39
44
|
|
|
40
45
|
Note: `viewports` may be empty for TypeScript tickets — that is expected.
|
|
@@ -41,9 +41,43 @@ from pathlib import Path
|
|
|
41
41
|
LOCAL_EVIDENCE_PATTERN = re.compile(r'\[(SCREENSHOT|EVIDENCE):\s*([^\]]+)\]')
|
|
42
42
|
|
|
43
43
|
|
|
44
|
+
def jira_config_candidates():
|
|
45
|
+
"""Return project-first jira-cli config candidates without duplicates."""
|
|
46
|
+
roots = []
|
|
47
|
+
project_dir = os.environ.get("CLAUDE_PROJECT_DIR", "").strip()
|
|
48
|
+
if project_dir:
|
|
49
|
+
roots.append(Path(project_dir).expanduser().resolve())
|
|
50
|
+
|
|
51
|
+
current = Path.cwd().resolve()
|
|
52
|
+
roots.extend([current, *current.parents])
|
|
53
|
+
|
|
54
|
+
candidates = []
|
|
55
|
+
seen = set()
|
|
56
|
+
for root in roots:
|
|
57
|
+
candidate = root / ".lisa" / "jira-cli" / ".config.yml"
|
|
58
|
+
key = str(candidate)
|
|
59
|
+
if key not in seen:
|
|
60
|
+
candidates.append(candidate)
|
|
61
|
+
seen.add(key)
|
|
62
|
+
|
|
63
|
+
home_candidate = (Path.home() / ".config" / ".jira" / ".config.yml").resolve()
|
|
64
|
+
if str(home_candidate) not in seen:
|
|
65
|
+
candidates.append(home_candidate)
|
|
66
|
+
return candidates
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def resolve_jira_config_path():
|
|
70
|
+
"""Resolve the first existing project config, then the home fallback."""
|
|
71
|
+
candidates = jira_config_candidates()
|
|
72
|
+
for candidate in candidates:
|
|
73
|
+
if candidate.exists():
|
|
74
|
+
return candidate
|
|
75
|
+
return candidates[-1]
|
|
76
|
+
|
|
77
|
+
|
|
44
78
|
def get_jira_config():
|
|
45
|
-
"""Read JIRA server and login from jira-cli config."""
|
|
46
|
-
config_path =
|
|
79
|
+
"""Read JIRA server and login from the project-first jira-cli config."""
|
|
80
|
+
config_path = resolve_jira_config_path()
|
|
47
81
|
if not config_path.exists():
|
|
48
82
|
print(f"ERROR: jira-cli config not found at {config_path}", file=sys.stderr)
|
|
49
83
|
sys.exit(1)
|
|
@@ -94,7 +94,7 @@ When invoked with `--rollup`, this skill **derives a parent/container ticket's s
|
|
|
94
94
|
| else any child has **started** (`In Progress` / `Code Review`, or shipped to an env while a sibling has not) | `claimed` | `In Progress` |
|
|
95
95
|
| else (children exist, none started) | — | unchanged — parent keeps its non-ready container status |
|
|
96
96
|
|
|
97
|
-
- **Blocked dominates** — a single blocked child surfaces `Blocked` on the parent even while siblings progress. It never says *which* child or *which kind* of hold; run `
|
|
97
|
+
- **Blocked dominates** — a single blocked child surfaces `Blocked` on the parent even while siblings progress. It never says *which* child or *which kind* of hold; resolve and run the shared classifier exactly as `lisa-tracker-sync` specifies, then carry its per-class report — blocking leaf, path, and who must act — into the rollup note. A missing classifier or non-zero exit is a strict **no-write** result: do not transition the parent and do not post/update a rollup comment; report the failure, never an all-clear. See `leaf-only-lifecycle` → **Classifying a hold**.
|
|
98
98
|
- **Least-advanced env wins** — the parent reaches an env only when every required child has reached at least that env; it never sits ahead of its laggard child. Apply native terminal resolution (the `leaf-only-lifecycle` Terminal native closure) only when the resolved env is the production `Done`, never at `On Dev`/`On Stg`.
|
|
99
99
|
- **"Required" children only** — won't-do / optional children do not hold the parent open.
|
|
100
100
|
- **Recursive** — an Epic reaches an env only when its Stories have themselves rolled up to at least that env; a Story reaches it only when its Sub-tasks have. Evaluate bottom-up.
|
|
@@ -85,22 +85,18 @@ All GraphQL calls use:
|
|
|
85
85
|
read_linear_key() {
|
|
86
86
|
[ -n "${LINEAR_API_KEY:-}" ] && { echo "$LINEAR_API_KEY"; return; }
|
|
87
87
|
|
|
88
|
-
# The ladder is ordered
|
|
89
|
-
#
|
|
90
|
-
#
|
|
91
|
-
#
|
|
92
|
-
# change untouched. The plugin rungs are the floor: `resolve-secret.mjs`
|
|
88
|
+
# The ladder is ordered across trusted machine-managed substrates and ends at
|
|
89
|
+
# the installed package. Checkout-local paths are deliberately absent: a
|
|
90
|
+
# familiar generated destination is still repository-controlled executable
|
|
91
|
+
# code. The plugin rungs are the floor: `resolve-secret.mjs`
|
|
93
92
|
# ships beside this skill, so a rung pointing at it is reachable from
|
|
94
93
|
# anywhere the plugin itself is installed. Without one, a repo that vendors
|
|
95
94
|
# none of the leading paths has no route to the key at all — which is what
|
|
96
95
|
# every consumer of this skill in a `.opencode`-layout repository actually
|
|
97
96
|
# hit, and why agents started improvising their own key lookups.
|
|
98
|
-
local
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
.opencode/skills/lisa/lisa-secrets-access/scripts/resolve-secret.mjs
|
|
102
|
-
.codex/skills/lisa/lisa-secrets-access/scripts/resolve-secret.mjs
|
|
103
|
-
)
|
|
97
|
+
# Execute only machine-managed plugin/package resolvers. Checkout-local
|
|
98
|
+
# candidates are repository-controlled code, not trusted merely by path.
|
|
99
|
+
local candidates=()
|
|
104
100
|
if [ -n "${CLAUDE_PLUGIN_ROOT:-}" ]; then
|
|
105
101
|
candidates+=("$CLAUDE_PLUGIN_ROOT/skills/lisa-secrets-access/scripts/resolve-secret.mjs")
|
|
106
102
|
fi
|
|
@@ -119,7 +115,7 @@ read_linear_key() {
|
|
|
119
115
|
local via_lisa
|
|
120
116
|
via_lisa=$(node "$resolver" get LINEAR_API_KEY 2>/dev/null) \
|
|
121
117
|
&& [ -n "$via_lisa" ] && { echo "$via_lisa"; return; }
|
|
122
|
-
|
|
118
|
+
# Empty/error means this substrate had no answer; try the next trusted one.
|
|
123
119
|
fi
|
|
124
120
|
done
|
|
125
121
|
|
|
@@ -140,7 +140,7 @@ When the caller passes `--rollup`, this skill **derives a parent/container's wor
|
|
|
140
140
|
| else any child has **started** (at the `claimed` state, at the `review` state where the project configures one, or shipped to an env while a sibling has not) | `claimed` | the configured `claimed` state |
|
|
141
141
|
| else (children exist, none started) | — | unchanged — parent keeps its non-ready container state |
|
|
142
142
|
|
|
143
|
-
- **Blocked dominates** — one blocked child surfaces `Blocked` on the parent even while siblings progress. It never says *which* child or *which kind* of hold; run `
|
|
143
|
+
- **Blocked dominates** — one blocked child surfaces `Blocked` on the parent even while siblings progress. It never says *which* child or *which kind* of hold; resolve and run the shared classifier exactly as `lisa-tracker-sync` specifies, then carry its per-class report — blocking leaf, path, and who must act — into the rollup note. A missing classifier or non-zero exit is a strict **no-write** result: do not save parent state and do not post/update a rollup comment; report the failure, never an all-clear. See `leaf-only-lifecycle` → **Classifying a hold**.
|
|
144
144
|
- **Least-advanced env wins** — the parent reaches an env only when every required child has reached at least that env; it never sits ahead of its laggard child. Native completion (moving the workflow `state` to Done) fires only when the resolved env is the production `Done`, never at `On Dev`/`On Stg`.
|
|
145
145
|
- **"Required" children only** — won't-do / optional (e.g. `Canceled`) children do not hold the parent open.
|
|
146
146
|
- **Recursive** — a Project reaches an env only when its Issues have themselves rolled up to at least that env. Evaluate bottom-up.
|
|
@@ -25,8 +25,14 @@ The caller provides pre-computed context:
|
|
|
25
25
|
9. Run the project's typecheck script with the provided package manager to catch type errors early — same reasoning as step 7, so `npm run typecheck` / `yarn typecheck` / `bun run typecheck`, falling back to `./node_modules/.bin/tsc --noEmit` rather than `npx tsc`:
|
|
26
26
|
|
|
27
27
|
```sh
|
|
28
|
+
case "$PACKAGE_MANAGER" in
|
|
29
|
+
npm) runner=(npm run) ;;
|
|
30
|
+
yarn) runner=(yarn) ;;
|
|
31
|
+
bun) runner=(bun run) ;;
|
|
32
|
+
*) echo "unsupported package manager: $PACKAGE_MANAGER" >&2; exit 2 ;;
|
|
33
|
+
esac
|
|
28
34
|
status=0
|
|
29
|
-
|
|
35
|
+
"${runner[@]}" typecheck >tsc.log 2>&1 || status=$?
|
|
30
36
|
head -n 30 tsc.log; echo "exit=$status"
|
|
31
37
|
```
|
|
32
38
|
|
|
@@ -58,9 +58,9 @@ read_notion_token() {
|
|
|
58
58
|
# OS keychain here — a second reader is how the same credential ends up living
|
|
59
59
|
# in two places and drifting.
|
|
60
60
|
#
|
|
61
|
-
# Ordered
|
|
62
|
-
#
|
|
63
|
-
#
|
|
61
|
+
# Ordered across trusted machine-managed substrates, ending at the installed
|
|
62
|
+
# package. Checkout-local paths are deliberately absent: a familiar generated
|
|
63
|
+
# destination is still repository-controlled executable code. The plugin
|
|
64
64
|
# rungs are the floor: `resolve-secret.mjs` ships beside this skill, so a rung
|
|
65
65
|
# pointing at it is reachable from anywhere the plugin itself is installed.
|
|
66
66
|
# Without one, a consumer repository that vendors none of the leading paths
|
|
@@ -69,12 +69,9 @@ read_notion_token() {
|
|
|
69
69
|
# lookups. This LADDER is identical in every skill that resolves a credential
|
|
70
70
|
# and `credential-resolver-ladder` fails if any copy diverges. Only what
|
|
71
71
|
# happens AFTER the ladder may differ between them.
|
|
72
|
-
local
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
.opencode/skills/lisa/lisa-secrets-access/scripts/resolve-secret.mjs
|
|
76
|
-
.codex/skills/lisa/lisa-secrets-access/scripts/resolve-secret.mjs
|
|
77
|
-
)
|
|
72
|
+
# Execute only machine-managed plugin/package resolvers. Checkout-local
|
|
73
|
+
# candidates are repository-controlled code, not trusted merely by path.
|
|
74
|
+
local candidates=()
|
|
78
75
|
if [ -n "${CLAUDE_PLUGIN_ROOT:-}" ]; then
|
|
79
76
|
candidates+=("$CLAUDE_PLUGIN_ROOT/skills/lisa-secrets-access/scripts/resolve-secret.mjs")
|
|
80
77
|
fi
|
|
@@ -93,7 +90,7 @@ read_notion_token() {
|
|
|
93
90
|
local via_lisa
|
|
94
91
|
via_lisa=$(node "$resolver" get NOTION_API_TOKEN 2>/dev/null) \
|
|
95
92
|
&& [ -n "$via_lisa" ] && { echo "$via_lisa"; return; }
|
|
96
|
-
|
|
93
|
+
# Empty/error means this substrate had no answer; try the next trusted one.
|
|
97
94
|
fi
|
|
98
95
|
done
|
|
99
96
|
# Legacy fallback: the OS keychain written by the guided /lisa:setup:notion
|
|
@@ -49,9 +49,9 @@ POSTHOG_HOST=${POSTHOG_HOST:-https://app.posthog.com}
|
|
|
49
49
|
read_posthog_key() {
|
|
50
50
|
[ -n "${POSTHOG_PERSONAL_API_KEY:-}" ] && { echo "$POSTHOG_PERSONAL_API_KEY"; return; }
|
|
51
51
|
#
|
|
52
|
-
# Ordered
|
|
53
|
-
#
|
|
54
|
-
#
|
|
52
|
+
# Ordered across trusted machine-managed substrates, ending at the installed
|
|
53
|
+
# package. Checkout-local paths are deliberately absent: a familiar generated
|
|
54
|
+
# destination is still repository-controlled executable code. The plugin
|
|
55
55
|
# rungs are the floor: `resolve-secret.mjs` ships beside this skill, so a rung
|
|
56
56
|
# pointing at it is reachable from anywhere the plugin itself is installed.
|
|
57
57
|
# Without one, a consumer repository that vendors none of the leading paths
|
|
@@ -60,12 +60,9 @@ read_posthog_key() {
|
|
|
60
60
|
# lookups. This LADDER is identical in every skill that resolves a credential
|
|
61
61
|
# and `credential-resolver-ladder` fails if any copy diverges. Only what
|
|
62
62
|
# happens AFTER the ladder may differ between them.
|
|
63
|
-
local
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
.opencode/skills/lisa/lisa-secrets-access/scripts/resolve-secret.mjs
|
|
67
|
-
.codex/skills/lisa/lisa-secrets-access/scripts/resolve-secret.mjs
|
|
68
|
-
)
|
|
63
|
+
# Execute only machine-managed plugin/package resolvers. Checkout-local
|
|
64
|
+
# candidates are repository-controlled code, not trusted merely by path.
|
|
65
|
+
local candidates=()
|
|
69
66
|
if [ -n "${CLAUDE_PLUGIN_ROOT:-}" ]; then
|
|
70
67
|
candidates+=("$CLAUDE_PLUGIN_ROOT/skills/lisa-secrets-access/scripts/resolve-secret.mjs")
|
|
71
68
|
fi
|
|
@@ -84,7 +81,7 @@ read_posthog_key() {
|
|
|
84
81
|
local via_lisa
|
|
85
82
|
via_lisa=$(node "$resolver" get POSTHOG_PERSONAL_API_KEY 2>/dev/null) \
|
|
86
83
|
&& [ -n "$via_lisa" ] && { echo "$via_lisa"; return; }
|
|
87
|
-
|
|
84
|
+
# Empty/error means this substrate had no answer; try the next trusted one.
|
|
88
85
|
fi
|
|
89
86
|
done
|
|
90
87
|
# Name every path. A bare `return 1` sends the next reader hunting for a
|